diff --git a/Makefile b/Makefile index 85abe5f..ac8bf0d 100644 --- a/Makefile +++ b/Makefile @@ -1,11 +1,11 @@ -OBJS = main.o plot3d.o input.o boundaryConditions.o eos.o primVars.o procBlock.o output.o matrix.o parallel.o slices.o turbulence.o gradients.o inviscidFlux.o viscousFlux.o source.o resid.o kdtree.o genArray.o fluxJacobian.o uncoupledScalar.o +OBJS = main.o plot3d.o input.o boundaryConditions.o eos.o primVars.o procBlock.o output.o matrix.o parallel.o slices.o turbulence.o inviscidFlux.o viscousFlux.o source.o resid.o kdtree.o genArray.o fluxJacobian.o uncoupledScalar.o utility.o CC = mpic++ -DEBUG = -ggdb -pg +DEBUG = -O0 -ggdb -pg OPTIM = -O3 -march=native PROF = -O3 -march=native -pg CODENAME = aither -CFLAGS = -std=c++14 -Wall -c $(OPTIM) -LFLAGS = -std=c++14 -Wall $(OPTIM) -o $(CODENAME) +CFLAGS = -std=c++14 -Wall -pedantic -c $(OPTIM) +LFLAGS = -std=c++14 -Wall -pedantic $(OPTIM) -o $(CODENAME) $(CODENAME) : $(OBJS) $(CC) $(LFLAGS) $(OBJS) @@ -13,7 +13,7 @@ $(CODENAME) : $(OBJS) plot3d.o : plot3d.cpp plot3d.hpp vector3d.hpp multiArray3d.hpp $(CC) $(CFLAGS) plot3d.cpp -main.o : main.cpp plot3d.hpp vector3d.hpp input.hpp procBlock.hpp eos.hpp primVars.hpp boundaryConditions.hpp inviscidFlux.hpp tensor.hpp viscousFlux.hpp output.hpp parallel.hpp turbulence.hpp gradients.hpp resid.hpp multiArray3d.hpp genArray.hpp +main.o : main.cpp plot3d.hpp vector3d.hpp input.hpp procBlock.hpp eos.hpp primVars.hpp boundaryConditions.hpp inviscidFlux.hpp tensor.hpp viscousFlux.hpp output.hpp parallel.hpp turbulence.hpp resid.hpp multiArray3d.hpp genArray.hpp fluxJacobian.hpp utility.hpp $(CC) $(CFLAGS) main.cpp input.o : input.cpp input.hpp boundaryConditions.hpp @@ -22,7 +22,7 @@ input.o : input.cpp input.hpp boundaryConditions.hpp primVars.o : primVars.cpp primVars.hpp vector3d.hpp eos.hpp inviscidFlux.hpp boundaryConditions.hpp input.hpp macros.hpp genArray.hpp $(CC) $(CFLAGS) primVars.cpp -procBlock.o : procBlock.cpp procBlock.hpp vector3d.hpp plot3d.hpp eos.hpp primVars.hpp inviscidFlux.hpp input.hpp genArray.hpp viscousFlux.hpp boundaryConditions.hpp macros.hpp turbulence.hpp kdtree.hpp uncoupledScalar.hpp fluxJacobian.hpp +procBlock.o : procBlock.cpp procBlock.hpp vector3d.hpp plot3d.hpp eos.hpp primVars.hpp inviscidFlux.hpp input.hpp genArray.hpp viscousFlux.hpp boundaryConditions.hpp macros.hpp turbulence.hpp kdtree.hpp uncoupledScalar.hpp fluxJacobian.hpp matrix.hpp utility.hpp $(CC) $(CFLAGS) procBlock.cpp inviscidFlux.o : inviscidFlux.cpp vector3d.hpp eos.hpp primVars.hpp inviscidFlux.hpp input.hpp macros.hpp genArray.hpp turbulence.hpp matrix.hpp @@ -52,26 +52,26 @@ matrix.o : matrix.cpp matrix.hpp macros.hpp genArray.hpp genArray.o : genArray.cpp genArray.hpp macros.hpp $(CC) $(CFLAGS) genArray.cpp -turbulence.o : turbulence.cpp turbulence.hpp +turbulence.o : turbulence.cpp turbulence.hpp matrix.hpp vector3d.hpp tensor.hpp primVars.hpp eos.hpp $(CC) $(CFLAGS) turbulence.cpp -source.o : source.cpp source.hpp macros.hpp turbulence.hpp primVars.hpp gradients.hpp +source.o : source.cpp source.hpp macros.hpp turbulence.hpp primVars.hpp matrix.hpp $(CC) $(CFLAGS) source.cpp -gradients.o : gradients.cpp gradients.hpp primVars.hpp vector3d.hpp tensor.hpp procBlock.hpp - $(CC) $(CFLAGS) gradients.cpp - resid.o : resid.cpp resid.hpp $(CC) $(CFLAGS) resid.cpp kdtree.o : kdtree.cpp kdtree.hpp vector3d.hpp $(CC) $(CFLAGS) kdtree.cpp -fluxJacobian.o : fluxJacobian.cpp fluxJacobian.hpp turbulence.hpp vector3d.hpp primVars.hpp eos.hpp input.hpp genArray.hpp matrix.hpp inviscidFlux.hpp uncoupledScalar.hpp +fluxJacobian.o : fluxJacobian.cpp fluxJacobian.hpp turbulence.hpp vector3d.hpp primVars.hpp eos.hpp input.hpp genArray.hpp matrix.hpp inviscidFlux.hpp uncoupledScalar.hpp tensor.hpp utility.hpp $(CC) $(CFLAGS) fluxJacobian.cpp uncoupledScalar.o : uncoupledScalar.cpp uncoupledScalar.hpp genArray.hpp $(CC) $(CFLAGS) uncoupledScalar.cpp +utility.o : utility.cpp utility.hpp genArray.hpp vector3d.hpp multiArray3d.hpp procBlock.hpp eos.hpp input.hpp turbulence.hpp slices.hpp fluxJacobian.hpp kdtree.hpp resid.hpp + $(CC) $(CFLAGS) utility.cpp + clean: rm *.o *~ $(CODENAME) diff --git a/README.md b/README.md index 7f781a5..1270ba0 100644 --- a/README.md +++ b/README.md @@ -4,15 +4,19 @@ This code is for a 3D Navier-Stokes computational fluid dynamics solver. It is a cell centered, structured solver, using mulit-block structured grids in Plot3D format. It uses explicit and implicit time integration methods. It uses MUSCL extrapolation to reconstruct the primative variables from the cell centers to the cell faces. The code uses the Roe flux difference splitting scheme for the inviscid fluxes, and a central scheme for the viscous fluxes. It is second order accurate in both space and time. ### Current Status -The code is 2nd order accurate in space and time. Available explicit time integration methods are forward euler (1st order) and a minimum storage four stage Runge-Kutta method (2nd order). The implicit solver (LU-SGS) is implemented for implicit time integration. Dual time stepping is implemented for time accuracy in the implicit solver. Available implicit time integrations methods come from the Beam and Warming family of methods and are the implicit euler (1st order), Crank-Nicholson (2nd order), and BDF2 (2nd order) methods. The code has been thoroughly commented. It has been made parallel using MPI. Currently the Wilcox K-Omega 2006 and SST 2003 turbulence models are available. +The code is 2nd order accurate in space and time. Available explicit time integration methods are forward euler (1st order) and a minimum storage four stage Runge-Kutta method (2nd order). The implicit solver (LU-SGS, BLU-SGS, DPLUR, BDPLUR) is implemented for implicit time integration. Dual time stepping is implemented for time accuracy in the implicit solver. Available implicit time integrations methods come from the Beam and Warming family of methods and are the implicit euler (1st order), Crank-Nicholson (2nd order), and BDF2 (2nd order) methods. The code has been thoroughly commented. It has been made parallel using MPI. Currently the Wilcox K-Omega 2006 and SST 2003 turbulence models are available. ### To Do List -* Implement block LUSGS implicit method +* Add build system (autotools or cmake) +* Add a library for matrix operations (Eigen and PETSc being considered) * Implement higher order state reconstruction for DES / Hybrid RANS/LES * Implement tubulence model for DES / Hybrid RANS/LES +### Dependencies +Aither depends on an MPI implementation. OpenMPI and MPICH have both been used in the past. Currently Aither is developed with OpenMPI. + ### How To compile -Assuming you have g++ (or equivalent) with c++14 support and some version of MPI (I use MPICH), just type 'make'. +Assuming you have a c++ compiler with c++14 support, just type 'make'. ### How To Run ```bash diff --git a/boundaryConditions.cpp b/boundaryConditions.cpp index 2160cc8..dd4f8b8 100644 --- a/boundaryConditions.cpp +++ b/boundaryConditions.cpp @@ -162,7 +162,7 @@ void boundaryConditions::BordersInterblock(const int &ii, << "Given index does not point to an interblock boundarySurface!" << endl; cerr << surf << endl; - exit(0); + exit(EXIT_FAILURE); } // Initialize array of bools to false (does not border interblock) @@ -341,7 +341,7 @@ vector GetInterblockBCs(const vector &bc, vector surfaceNums; // surface number of interblock // loop over all blocks - for (auto ii = 0; ii < static_cast(bc.size()); ii++) { + for (auto ii = 0U; ii < bc.size(); ii++) { // Loop over number of surfaces in block for (auto jj = 0; jj < bc[ii].NumSurfaces(); jj++) { // If boundary condition is interblock, store data @@ -363,11 +363,10 @@ vector GetInterblockBCs(const vector &bc, // Loop over isolated interblocks // ii counts by two because after a pair is found, that data is swapped // to ii+1. This allows the next search to avoid the matched pair - for (auto ii = 0; ii < static_cast(isolatedInterblocks.size()); + for (auto ii = 0U; ii < isolatedInterblocks.size(); ii += 2) { // Loop over possible matches - for (auto jj = ii + 1; jj < - static_cast(isolatedInterblocks.size()); jj++) { + for (auto jj = ii + 1U; jj < isolatedInterblocks.size(); jj++) { // Blocks and boundary surfaces between interblocks match // blocks between interblock BCs match if (isolatedInterblocks[ii].PartnerBlock() == numRankPos[jj][0] && @@ -736,7 +735,7 @@ void interblock::UpdateBorderFirst(const int &a) { cerr << "ERROR: Error in interblock::UpdateBorderFirst(). " << "Position to update is out of range. Choose between 0-3. " << "Position input was " << a << endl; - exit(0); + exit(EXIT_FAILURE); } } @@ -760,7 +759,7 @@ void interblock::UpdateBorderSecond(const int &a) { cerr << "ERROR: Error in interblock::UpdateBorderSecond(). " << "Position to update is out of range. Choose between 0-3. " << "Position input was " << a << endl; - exit(0); + exit(EXIT_FAILURE); } } @@ -825,7 +824,7 @@ void interblock::FirstSliceIndices(int &is1, int &ie1, int &js1, int &je1, } else { cerr << "ERROR: Error in interblock::FirstSliceIndices(). Surface boundary " << this->BoundaryFirst() << " is not recognized!" << endl; - exit(0); + exit(EXIT_FAILURE); } } @@ -891,7 +890,7 @@ void interblock::SecondSliceIndices(int &is2, int &ie2, int &js2, int &je2, cerr << "ERROR: Error in interblock::SecondSliceIndices(). " << "Surface boundary " << this->BoundarySecond() << " is not recognized!" << endl; - exit(0); + exit(EXIT_FAILURE); } } @@ -931,20 +930,20 @@ int boundaryConditions::BlockDimK() const { } /* Member function to split boundary_ conditions along a given direction at a - given - index. The calling instance retains the lower portion of the split, and the - returned instance is the upper portion. */ + given index. The calling instance retains the lower portion of the split, + and the returned instance is the upper portion. */ boundaryConditions boundaryConditions::Split(const string &dir, const int &ind, const int &numBlk, const int &newBlkNum, vector &aSurf) { // dir -- direction to split it (i, j, k) // ind -- index of cell to split at - // (this index is the last cell that remains in the lower split) + // (this index is the last cell that remains in the lower split) // numBlk -- block_ number that (*this) is assocatied with // newBlkNum -- block_ number for upper split // aSurf -- vector of any interblocks that are split, - // because their partners will need to be altered for the split as well + // because their partners will need to be altered for the split as + // well // +1 because boundaries (in boundaryConditions) start at 1, not 0 const auto indNG = ind + 1; @@ -1004,7 +1003,7 @@ boundaryConditions boundaryConditions::Split(const string &dir, const int &ind, // At upper i surface, lower bc is now interface // upper surface matches with lower surface const auto tag = 1000 + newBlkNum; - bound1.surfs_[ii].bcType_ = "interblock"; // bcType_ + bound1.surfs_[ii].bcType_ = "interblock"; // bcType bound1.surfs_[ii].data_[0] = indNG; // imin bound1.surfs_[ii].data_[1] = indNG; // imax bound1.surfs_[ii].data_[6] = tag; // tag @@ -1035,7 +1034,7 @@ boundaryConditions boundaryConditions::Split(const string &dir, const int &ind, } } else { // j-surface or k-surface // At j/k surface, if bc is interblock, store boundarySurface - // because partner block_ BC will need to be updated + // because partner block BC will need to be updated if (this->GetBCTypes(ii) == "interblock") { alteredSurf.push_back(this->GetSurface(ii)); } @@ -1070,18 +1069,23 @@ boundaryConditions boundaryConditions::Split(const string &dir, const int &ind, // Delete unnecessary boundaries and change number of surfaces in i,j,k // to appropriate number - for (auto ii = 0; ii < static_cast(del1.size()); ii++) { + + // need to delete from bottom of vector so indices are preserved + // need to cast to int because value must be negative for termination + for (auto ii = static_cast(del1.size()) - 1; ii >= 0; --ii) { bound1.surfs_.erase(bound1.surfs_.begin() + del1[ii]); - bound1.numSurfI_ -= del1I; - bound1.numSurfJ_ -= del1J; - bound1.numSurfK_ -= del1K; } - for (auto ii = 0; ii < static_cast(del2.size()); ii++) { + bound1.numSurfI_ -= del1I; + bound1.numSurfJ_ -= del1J; + bound1.numSurfK_ -= del1K; + + for (auto ii = static_cast(del2.size()) - 1; ii >= 0; --ii) { bound2.surfs_.erase(bound2.surfs_.begin() + del2[ii]); - bound2.numSurfI_ -= del2I; - bound2.numSurfJ_ -= del2J; - bound2.numSurfK_ -= del2K; } + bound2.numSurfI_ -= del2I; + bound2.numSurfJ_ -= del2J; + bound2.numSurfK_ -= del2K; + } else if (dir == "j") { // split along j-plane // Initialize deletion numbers to 0 auto del1I = 0; @@ -1142,7 +1146,7 @@ boundaryConditions boundaryConditions::Split(const string &dir, const int &ind, numInterU++; // At upper j surface, upper bc is same as original, but indices - // are adjusted for new block_ size + // are adjusted for new block size bound2.surfs_[ii].data_[2] = this->GetJMax(ii) - indNG + 1; // jmin bound2.surfs_[ii].data_[3] = this->GetJMax(ii) - indNG + 1; // jmax @@ -1186,18 +1190,23 @@ boundaryConditions boundaryConditions::Split(const string &dir, const int &ind, // Delete unnecessary boundaries - and set number of surfaces (i, j, k) // to appropriate number - for (auto ii = 0; ii < static_cast(del1.size()); ii++) { + + // need to delete from bottom of vector so indices are preserved + // need to cast to int because value must be negative for termination + for (auto ii = static_cast(del1.size()) - 1; ii >= 0; --ii) { bound1.surfs_.erase(bound1.surfs_.begin() + del1[ii]); - bound1.numSurfI_ -= del1I; - bound1.numSurfJ_ -= del1J; - bound1.numSurfK_ -= del1K; } - for (auto ii = 0; ii < static_cast(del2.size()); ii++) { + bound1.numSurfI_ -= del1I; + bound1.numSurfJ_ -= del1J; + bound1.numSurfK_ -= del1K; + + for (auto ii = static_cast(del2.size()) - 1; ii >= 0; --ii) { bound2.surfs_.erase(bound2.surfs_.begin() + del2[ii]); - bound2.numSurfI_ -= del2I; - bound2.numSurfJ_ -= del2J; - bound2.numSurfK_ -= del2K; } + bound2.numSurfI_ -= del2I; + bound2.numSurfJ_ -= del2J; + bound2.numSurfK_ -= del2K; + } else if (dir == "k") { // split along k-plane // Initialize deletion numbers to 0 auto del1I = 0; @@ -1301,21 +1310,27 @@ boundaryConditions boundaryConditions::Split(const string &dir, const int &ind, // Delete unnecessary boundaries and set surface numbers (i,j,k) to // appropriate value - for (auto ii = 0; ii < static_cast(del1.size()); ii++) { + + // need to delete from bottom of vector so indices are preserved + // need to cast to int because value must be negative for termination + for (auto ii = static_cast(del1.size()) - 1; ii >= 0; --ii) { bound1.surfs_.erase(bound1.surfs_.begin() + del1[ii]); - bound1.numSurfI_ -= del1I; - bound1.numSurfJ_ -= del1J; } - for (auto ii = 0; ii < static_cast(del2.size()); ii++) { + bound1.numSurfI_ -= del1I; + bound1.numSurfJ_ -= del1J; + bound1.numSurfK_ -= del1K; + + for (auto ii = static_cast(del2.size()) - 1; ii >= 0; --ii) { bound2.surfs_.erase(bound2.surfs_.begin() + del2[ii]); - bound2.numSurfI_ -= del2I; - bound2.numSurfJ_ -= del2J; - bound2.numSurfK_ -= del2K; } + bound2.numSurfI_ -= del2I; + bound2.numSurfJ_ -= del2J; + bound2.numSurfK_ -= del2K; + } else { cerr << "ERROR: Error in boundaryCondition::Split(). Direction " << dir << " is not recognized! Choose either i, j, or k." << endl; - exit(0); + exit(EXIT_FAILURE); } (*this) = bound1; // assign lower split to (*this) @@ -1379,7 +1394,7 @@ void boundaryConditions::DependentSplit(const boundarySurface &surf, cerr << "ERROR: Error in boundaryConditions::DependentSplit(). " "Direction " << dir << " is not recognized." << endl; cerr << "Please choose i, j, or k." << endl; - exit(0); + exit(EXIT_FAILURE); } } else if (match.Orientation() == 2) { // D1/D2 swapped @@ -1401,7 +1416,7 @@ void boundaryConditions::DependentSplit(const boundarySurface &surf, cerr << "ERROR: Error in boundaryConditions::DependentSplit(). " "Direction " << dir << " is not recognized." << endl; cerr << "Please choose i, j, or k." << endl; - exit(0); + exit(EXIT_FAILURE); } } else if (match.Orientation() == 3) { // D1 reversed @@ -1424,7 +1439,7 @@ void boundaryConditions::DependentSplit(const boundarySurface &surf, cerr << "ERROR: Error in boundaryConditions::DependentSplit(). " "Direction " << dir << " is not recognized." << endl; cerr << "Please choose i, j, or k." << endl; - exit(0); + exit(EXIT_FAILURE); } } else if (match.Orientation() == 4) { // D1/D2 swapped, D1 reversed @@ -1447,7 +1462,7 @@ void boundaryConditions::DependentSplit(const boundarySurface &surf, cerr << "ERROR: Error in boundaryConditions::DependentSplit(). " "Direction " << dir << " is not recognized." << endl; cerr << "Please choose i, j, or k." << endl; - exit(0); + exit(EXIT_FAILURE); } } else if (match.Orientation() == 5) { // D1/D2 swapped, D2 reversed @@ -1470,7 +1485,7 @@ void boundaryConditions::DependentSplit(const boundarySurface &surf, cerr << "ERROR: Error in boundaryConditions::DependentSplit(). " "Direction " << dir << " is not recognized." << endl; cerr << "Please choose i, j, or k." << endl; - exit(0); + exit(EXIT_FAILURE); } } else if (match.Orientation() == 6) { // D2 reversed @@ -1493,7 +1508,7 @@ void boundaryConditions::DependentSplit(const boundarySurface &surf, cerr << "ERROR: Error in boundaryConditions::DependentSplit(). " "Direction " << dir << " is not recognized." << endl; cerr << "Please choose i, j, or k." << endl; - exit(0); + exit(EXIT_FAILURE); } } else if (match.Orientation() == 7) { // D1/D2 swapped and reversed @@ -1517,7 +1532,7 @@ void boundaryConditions::DependentSplit(const boundarySurface &surf, cerr << "ERROR: Error in boundaryConditions::DependentSplit(). " "Direction " << dir << " is not recognized." << endl; cerr << "Please choose i, j, or k." << endl; - exit(0); + exit(EXIT_FAILURE); } } else { // D1/D2 reversed (orientation 8) @@ -1541,7 +1556,7 @@ void boundaryConditions::DependentSplit(const boundarySurface &surf, cerr << "ERROR: Error in boundaryConditions::DependentSplit(). " "Direction " << dir << " is not recognized." << endl; cerr << "Please choose i, j, or k." << endl; - exit(0); + exit(EXIT_FAILURE); } } @@ -1936,7 +1951,7 @@ void boundaryConditions::Join(const boundaryConditions &bc, const string &dir, } else { cerr << "ERROR: Error in procBlock::Join(). Direction " << dir << " is not recognized! Choose either i, j, or k." << endl; - exit(0); + exit(EXIT_FAILURE); } aSurf = alteredSurf; @@ -2058,7 +2073,7 @@ patch::patch(const int &bound, const int &b, const int &d1s, const int &d1e, cerr << "ERROR: Error in patch::patch(). Boundary surface " << bound << " is not recognized!" << endl; cerr << "Choose an integer between 1-6." << endl; - exit(0); + exit(EXIT_FAILURE); } } @@ -2097,7 +2112,7 @@ void boundaryConditions::PackBC(char *(&sendBuffer), const int &sendBufSize, // get string lengths for each boundary_ condition to be sent, so processors // unpacking know how much data to unpack for each string vector strLength(this->NumSurfaces()); - for (auto jj = 0; jj < static_cast(strLength.size()); jj++) { + for (auto jj = 0U; jj < strLength.size(); jj++) { // +1 for c_str end character strLength[jj] = this->GetBCTypes(jj).size() + 1; } @@ -2155,7 +2170,7 @@ void boundaryConditions::UnpackBC(char *(&recvBuffer), const int &recvBufSize, MPI_Unpack(recvBuffer, recvBufSize, &position, &strLength[0], strLength.size(), MPI_INT, MPI_COMM_WORLD); // unpack string sizes // unpack boundary condition names - for (auto jj = 0; jj < static_cast(strLength.size()); jj++) { + for (auto jj = 0U; jj < strLength.size(); jj++) { auto *nameBuf = new char[strLength[jj]]; // allocate buffer to store BC // name MPI_Unpack(recvBuffer, recvBufSize, &position, &nameBuf[0], strLength[jj], @@ -2219,7 +2234,7 @@ int boundarySurface::SurfaceType() const { cerr << "ERROR: Error in boundarySurface::SurfaceType(). Surface is " "defined incorrectly, it is neither an i, j, or k surface." << endl; cerr << (*this) << endl; - exit(0); + exit(EXIT_FAILURE); } return surf; @@ -2232,7 +2247,7 @@ int boundarySurface::PartnerBlock() const { if (bcType_ != "interblock") { cerr << "ERROR: Partner blocks are only associated with interblock " "boundaries. Current boundary_ is " << bcType_ << endl; - exit(0); + exit(EXIT_FAILURE); } const auto subtract = this->PartnerSurface() * 1000; @@ -2246,7 +2261,7 @@ int boundarySurface::PartnerSurface() const { if (bcType_ != "interblock") { cerr << "ERROR: Partner blocks are only associated with interblock " "boundaries. Current boundary_ is " << bcType_ << endl; - exit(0); + exit(EXIT_FAILURE); } auto surf = 0; @@ -2267,7 +2282,7 @@ int boundarySurface::PartnerSurface() const { cerr << "ERROR: Error in boundarySurface::PartnerSurface(). Tag does not " "fit in range. Tag must be between 1000 and 6999." << endl; cerr << (*this) << endl; - exit(0); + exit(EXIT_FAILURE); } return surf; @@ -2409,7 +2424,7 @@ void boundarySurface::UpdateTagForSplitJoin(const int &nBlk) { if (bcType_ != "interblock") { cerr << "ERROR: Only tags associated with interblock boundaries need to be " "updated. Current boundary_ is " << bcType_ << endl; - exit(0); + exit(EXIT_FAILURE); } data_[6] = this->PartnerSurface() * 1000 + nBlk; @@ -2536,7 +2551,7 @@ boundarySurface boundarySurface::Split(const string &dir, const int &ind, } else { cerr << "ERROR: Error in boundarySurface::Split(). Direction " << dir << " is not recognized! Choose either i, j, or k." << endl; - exit(0); + exit(EXIT_FAILURE); } (*this) = surf1; // return lower surface as (*this) @@ -2589,7 +2604,7 @@ bool boundarySurface::SplitDirectionIsReversed(const string &dir, } else { cerr << "ERROR: Error in boundarySurface::SplitDirectionIsReversed(). " "Direction " << dir << " does not match i, j, or k!" << endl; - exit(0); + exit(EXIT_FAILURE); } return isReversed; @@ -2640,7 +2655,7 @@ vector3d GetSwapLoc(const int &l1, const int &l2, const int &l3, } else { cerr << "ERROR: Error in procBlock:GetSwapLoc(). Boundary direction " << inter.Direction3First() << " is not recognized!" << endl; - exit(0); + exit(EXIT_FAILURE); } //-------------------------------------------------------------------------- // need to use orientation for second in pair @@ -2747,7 +2762,7 @@ vector3d GetSwapLoc(const int &l1, const int &l2, const int &l3, } else { cerr << "ERROR: Error in procBlock.cpp:GetSwapLoc(). Boundary surface of " << inter.Direction3Second() << " is not recognized!" << endl; - exit(0); + exit(EXIT_FAILURE); } } diff --git a/fluxJacobian.cpp b/fluxJacobian.cpp index 2b5ba57..6b35e77 100644 --- a/fluxJacobian.cpp +++ b/fluxJacobian.cpp @@ -14,9 +14,10 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ +#include // cout #include // sqrt -#include #include +#include #include // max #include "fluxJacobian.hpp" #include "turbulence.hpp" // turbModel @@ -24,13 +25,14 @@ #include "primVars.hpp" // primVars #include "genArray.hpp" // genArray #include "inviscidFlux.hpp" // ConvectiveFluxUpdate +#include "utility.hpp" // TauNormal using std::cout; using std::endl; using std::cerr; using std::vector; using std::string; -using std:: unique_ptr; +using std::unique_ptr; // constructor // if constructed with two doubles, create scalar squareMatrix @@ -63,7 +65,7 @@ genArray fluxJacobian::ArrayMult(genArray arr) const { arr[6] *= turbJacobian_(0, 0); } else { arr = flowJacobian_.ArrayMult(arr); - arr = turbJacobian_.ArrayMult(arr, NUMFLOWVARS); + arr = turbJacobian_.ArrayMult(arr, flowJacobian_.Size()); } return arr; } @@ -95,61 +97,52 @@ jacobians. In the above equations the dissipation term L is held constant during differentiation. A represents the convective flux jacobian matrix. */ -void fluxJacobian::RusanovFluxJacobian(const primVars &left, - const primVars &right, +void fluxJacobian::RusanovFluxJacobian(const primVars &state, const idealGas &eos, - const vector3d &areaNorm, + const unitVec3dMag &area, const bool &positive, - const input &inp) { - // left -- primative variables from left side - // right -- primative variables from right side + const input &inp, + const unique_ptr &turb) { + // state -- primative variables at face // eos -- ideal gas equation of state - // areaNorm -- face area vector + // area -- face area vector // positive -- flag to determine whether to add or subtract dissipation // inp -- input variables + // turb -- turbulence model - // dot product of velocities with unit area vector - const auto specRad = std::max(fabs(left.Velocity().DotProd(areaNorm)) + - left.SoS(eos), - fabs(right.Velocity().DotProd(areaNorm)) + - right.SoS(eos)); + // face inviscid spectral radius + const auto specRad = state.InvFaceSpectralRadius(area, eos); // form dissipation matrix based on spectral radius fluxJacobian dissipation(inp.NumFlowEquations(), inp.NumTurbEquations()); dissipation.flowJacobian_.Identity(); dissipation.flowJacobian_ *= specRad; - // begin jacobian calculation - positive ? this->InvFluxJacobian(left, eos, areaNorm, inp) : - this->InvFluxJacobian(right, eos, areaNorm, inp); - + this->InvFluxJacobian(state, eos, area, inp, turb); - // compute turbulent jacobian if necessary + // compute turbulent dissipation if necessary if (inp.IsTurbulent()) { - dissipation.turbJacobian_.Identity(); - - const auto turbSpecRad = std::max(fabs(left.Velocity().DotProd(areaNorm)), - fabs(right.Velocity().DotProd(areaNorm))); - - dissipation.turbJacobian_ *= turbSpecRad; + // multiply by 0.5 b/c averaging with convection matrix + dissipation.turbJacobian_ = 0.5 * turb->InviscidDissJacobian(state, area); } positive ? (*this) += dissipation : (*this) -= dissipation; - (*this) *= 0.5; } // function to calculate inviscid flux jacobian void fluxJacobian::InvFluxJacobian(const primVars &state, const idealGas &eqnState, - const vector3d &areaNorm, - const input &inp) { - // state -- primative variables from left side + const unitVec3dMag &area, + const input &inp, + const unique_ptr &turb) { + // state -- primative variables at face // eqnState -- ideal gas equation of state - // areaNorm -- face area vector + // area -- face area vector // inp -- input variables + // turb -- turbulence model - const auto velNorm = state.Velocity().DotProd(areaNorm); + const auto velNorm = state.Velocity().DotProd(area.UnitVector()); const auto gammaMinusOne = eqnState.Gamma() - 1.0; const auto phi = 0.5 * gammaMinusOne * state.Velocity().MagSq(); const auto a1 = eqnState.Gamma() * state.Energy(eqnState) - phi; @@ -162,49 +155,55 @@ void fluxJacobian::InvFluxJacobian(const primVars &state, // calculate flux derivatives wrt left state // column zero flowJacobian_(0, 0) = 0.0; - flowJacobian_(1, 0) = phi * areaNorm.X() - state.U() * velNorm; - flowJacobian_(2, 0) = phi * areaNorm.Y() - state.V() * velNorm; - flowJacobian_(3, 0) = phi * areaNorm.Z() - state.W() * velNorm; + flowJacobian_(1, 0) = phi * area.UnitVector().X() - state.U() * velNorm; + flowJacobian_(2, 0) = phi * area.UnitVector().Y() - state.V() * velNorm; + flowJacobian_(3, 0) = phi * area.UnitVector().Z() - state.W() * velNorm; flowJacobian_(4, 0) = velNorm * (phi - a1); // column one - flowJacobian_(0, 1) = areaNorm.X(); - flowJacobian_(1, 1) = velNorm - a3 * areaNorm.X() * state.U(); - flowJacobian_(2, 1) = state.V() * areaNorm.X() - - gammaMinusOne * state.U() * areaNorm.Y(); - flowJacobian_(3, 1) = state.W() * areaNorm.X() - - gammaMinusOne * state.U() * areaNorm.Z(); - flowJacobian_(4, 1) = a1 * areaNorm.X() - gammaMinusOne * state.U() * velNorm; + flowJacobian_(0, 1) = area.UnitVector().X(); + flowJacobian_(1, 1) = velNorm - a3 * area.UnitVector().X() * state.U(); + flowJacobian_(2, 1) = state.V() * area.UnitVector().X() - + gammaMinusOne * state.U() * area.UnitVector().Y(); + flowJacobian_(3, 1) = state.W() * area.UnitVector().X() - + gammaMinusOne * state.U() * area.UnitVector().Z(); + flowJacobian_(4, 1) = a1 * area.UnitVector().X() - gammaMinusOne * state.U() + * velNorm; // column two - flowJacobian_(0, 2) = areaNorm.Y(); - flowJacobian_(1, 2) = state.U() * areaNorm.Y() - - gammaMinusOne * state.V() * areaNorm.X(); - flowJacobian_(2, 2) = velNorm - a3 * areaNorm.Y() * state.V(); - flowJacobian_(3, 2) = state.W() * areaNorm.Y() - - gammaMinusOne * state.V() * areaNorm.Z(); - flowJacobian_(4, 2) = a1 * areaNorm.Y() - gammaMinusOne * state.V() * velNorm; + flowJacobian_(0, 2) = area.UnitVector().Y(); + flowJacobian_(1, 2) = state.U() * area.UnitVector().Y() - + gammaMinusOne * state.V() * area.UnitVector().X(); + flowJacobian_(2, 2) = velNorm - a3 * area.UnitVector().Y() * state.V(); + flowJacobian_(3, 2) = state.W() * area.UnitVector().Y() - + gammaMinusOne * state.V() * area.UnitVector().Z(); + flowJacobian_(4, 2) = a1 * area.UnitVector().Y() - gammaMinusOne * state.V() + * velNorm; // column three - flowJacobian_(0, 3) = areaNorm.Z(); - flowJacobian_(1, 3) = state.U() * areaNorm.Z() - - gammaMinusOne * state.W() * areaNorm.X(); - flowJacobian_(2, 3) = state.V() * areaNorm.Z() - - gammaMinusOne * state.W() * areaNorm.Y(); - flowJacobian_(3, 3) = velNorm - a3 * areaNorm.Z() * state.W(); - flowJacobian_(4, 3) = a1 * areaNorm.Z() - gammaMinusOne * state.W() * velNorm; + flowJacobian_(0, 3) = area.UnitVector().Z(); + flowJacobian_(1, 3) = state.U() * area.UnitVector().Z() - + gammaMinusOne * state.W() * area.UnitVector().X(); + flowJacobian_(2, 3) = state.V() * area.UnitVector().Z() - + gammaMinusOne * state.W() * area.UnitVector().Y(); + flowJacobian_(3, 3) = velNorm - a3 * area.UnitVector().Z() * state.W(); + flowJacobian_(4, 3) = a1 * area.UnitVector().Z() - gammaMinusOne * state.W() + * velNorm; // column four flowJacobian_(0, 4) = 0.0; - flowJacobian_(1, 4) = gammaMinusOne * areaNorm.X(); - flowJacobian_(2, 4) = gammaMinusOne * areaNorm.Y(); - flowJacobian_(3, 4) = gammaMinusOne * areaNorm.Z(); + flowJacobian_(1, 4) = gammaMinusOne * area.UnitVector().X(); + flowJacobian_(2, 4) = gammaMinusOne * area.UnitVector().Y(); + flowJacobian_(3, 4) = gammaMinusOne * area.UnitVector().Z(); flowJacobian_(4, 4) = eqnState.Gamma() * velNorm; + // multiply by 0.5 b/c averaging with dissipation matrix + flowJacobian_ *= 0.5 * area.Mag(); + // turbulent jacobian here if (inp.IsTurbulent()) { - turbJacobian_(0, 0) = velNorm; - turbJacobian_(1, 1) = velNorm; + // multiply by 0.5 b/c averaging with dissipation matrix + turbJacobian_ = 0.5 * turb->InviscidConvJacobian(state, area); } } @@ -225,32 +224,33 @@ differentiation. A represents the convective flux jacobian matrix. void fluxJacobian::ApproxRoeFluxJacobian(const primVars &left, const primVars &right, const idealGas &eos, - const vector3d &areaNorm, + const unitVec3dMag &area, const bool &positive, - const input &inp) { + const input &inp, + const unique_ptr &turb) { // left -- primative variables from left side // right -- primative variables from right side // eos -- ideal gas equation of state - // areaNorm -- face unit area vector + // area -- face area vector // positive -- flag to determine whether to add or subtract dissipation // inp -- input variables - + // turb -- turbulence model + // compute Roe averaged state const auto roeAvg = RoeAveragedState(left, right, eos); // compute Roe matrix fluxJacobian roeMatrix; - roeMatrix.InvFluxJacobian(roeAvg, eos, areaNorm, inp); + roeMatrix.InvFluxJacobian(roeAvg, eos, area, inp, turb); // compute convective flux jacobian - positive ? this->InvFluxJacobian(left, eos, areaNorm, inp) : - this->InvFluxJacobian(right, eos, areaNorm, inp); + positive ? this->InvFluxJacobian(left, eos, area, inp, turb) : + this->InvFluxJacobian(right, eos, area, inp, turb); positive ? (*this) += roeMatrix : (*this) -= roeMatrix; - (*this) *= 0.5; } -// change of variable matrix going frim primative to conservative variables +// change of variable matrix going from primative to conservative variables // from Dwight void fluxJacobian::DelPrimativeDelConservative(const primVars &state, const idealGas &eos, @@ -265,7 +265,7 @@ void fluxJacobian::DelPrimativeDelConservative(const primVars &state, flowJacobian_ = squareMatrix(inp.NumFlowEquations()); turbJacobian_ = squareMatrix(inp.NumTurbEquations()); - // assign first column + // assign column 0 flowJacobian_(0, 0) = 1.0; flowJacobian_(1, 0) = -invRho * state.U(); flowJacobian_(2, 0) = -invRho * state.V(); @@ -273,19 +273,19 @@ void fluxJacobian::DelPrimativeDelConservative(const primVars &state, flowJacobian_(4, 0) = 0.5 * gammaMinusOne * state.Velocity().DotProd(state.Velocity()); - // assign second column + // assign column 1 flowJacobian_(1, 1) = invRho; flowJacobian_(4, 1) = -gammaMinusOne * state.U(); - // assign third column + // assign column 2 flowJacobian_(2, 2) = invRho; flowJacobian_(4, 2) = -gammaMinusOne * state.V(); - // assign fourth column + // assign column 3 flowJacobian_(3, 3) = invRho; flowJacobian_(4, 3) = -gammaMinusOne * state.W(); - // assign fifth column + // assign column 4 flowJacobian_(4, 4) = gammaMinusOne; // turbulent jacobian here @@ -297,171 +297,320 @@ void fluxJacobian::DelPrimativeDelConservative(const primVars &state, // approximate thin shear layer jacobian following implementation in Dwight. // does not use any gradients -void fluxJacobian::ApproxTSLJacobian(const primVars &state, const idealGas &eos, +void fluxJacobian::ApproxTSLJacobian(const primVars &state, + const double &lamVisc, + const double &turbVisc, const double &f1, + const idealGas &eos, const sutherland &suth, - const vector3d &area, + const unitVec3dMag &area, const double &dist, const unique_ptr &turb, - const input &inp) { + const input &inp, const bool &left, + const tensor &vGrad) { // state -- primative variables // eos -- equation of state // suth -- sutherland's law for viscosity - // area -- face area unit vector + // area -- face area vector // dist -- distance from cell center to cell center // turb -- turbulence model // inp -- input variables + // left -- flag that is negative if using left state + // vGrad -- velocity gradient flowJacobian_ = squareMatrix(inp.NumFlowEquations()); turbJacobian_ = squareMatrix(inp.NumTurbEquations()); - const auto mu = suth.EffectiveViscosity(state.Temperature(eos)); - const auto mut = turb->EddyViscNoLim(state) * suth.NondimScaling(); - const auto velNorm = state.Velocity().DotProd(area); + const auto mu = suth.NondimScaling() * lamVisc; + const auto mut = suth.NondimScaling() * turbVisc; + const auto velNorm = state.Velocity().DotProd(area.UnitVector()); + + const auto tauNorm = TauNormal(vGrad, area.UnitVector(), mu, mut, suth); - // assign first column - flowJacobian_(4, 0) = -eos.Conductivity(mu + mut) * state.Temperature(eos) / - ((mu + mut) * state.Rho()); + auto fac = left ? -1.0 : 1.0; - // assign second column - flowJacobian_(1, 1) = (1.0 / 3.0) * area.X() * area.X() + 1.0; - flowJacobian_(1, 2) = (1.0 / 3.0) * area.X() * area.Y(); - flowJacobian_(1, 3) = (1.0 / 3.0) * area.X() * area.Z(); - flowJacobian_(1, 4) = (1.0 / 3.0) * area.X() * velNorm + state.U(); + constexpr auto third = 1.0 / 3.0; - // assign third column - flowJacobian_(2, 1) = (1.0 / 3.0) * area.Y() * area.X(); - flowJacobian_(2, 2) = (1.0 / 3.0) * area.Y() * area.Y() + 1.0; - flowJacobian_(2, 3) = (1.0 / 3.0) * area.Y() * area.Z(); - flowJacobian_(2, 4) = (1.0 / 3.0) * area.Y() * velNorm + state.V(); + // assign column 0 + flowJacobian_(4, 0) = -(eos.Conductivity(mu) + + eos.TurbConductivity(mut, turb->TurbPrandtlNumber())) + * state.Temperature(eos) / ((mu + mut) * state.Rho()); - // assign fourth column - flowJacobian_(3, 1) = (1.0 / 3.0) * area.Z() * area.X(); - flowJacobian_(3, 2) = (1.0 / 3.0) * area.Z() * area.Y(); - flowJacobian_(3, 3) = (1.0 / 3.0) * area.Z() * area.Z() + 1.0; - flowJacobian_(3, 4) = (1.0 / 3.0) * area.Z() * velNorm + state.W(); + // assign column 1 + flowJacobian_(1, 1) = third * area.UnitVector().X() * area.UnitVector().X() + + 1.0; + flowJacobian_(2, 1) = third * area.UnitVector().X() * area.UnitVector().Y(); + flowJacobian_(3, 1) = third * area.UnitVector().X() * area.UnitVector().Z(); + flowJacobian_(4, 1) = fac * 0.5 * dist / (mu + mut) * tauNorm.X() + + third * area.UnitVector().X() * velNorm + state.U(); - // assign fifth column - flowJacobian_(4, 4) = eos.Conductivity(mu + mut) / ((mu + mut) * state.Rho()); + // assign column 2 + flowJacobian_(1, 2) = third * area.UnitVector().Y() * area.UnitVector().X(); + flowJacobian_(2, 2) = third * area.UnitVector().Y() * area.UnitVector().Y() + + 1.0; + flowJacobian_(3, 2) = third * area.UnitVector().Y() * area.UnitVector().Z(); + flowJacobian_(4, 2) = fac * 0.5 * dist / (mu + mut) * tauNorm.Y() + + third * area.UnitVector().Y() * velNorm + state.V(); - flowJacobian_ *= (mu + mut) / dist; + // assign column 3 + flowJacobian_(1, 3) = third * area.UnitVector().Z() * area.UnitVector().X(); + flowJacobian_(2, 3) = third * area.UnitVector().Z() * area.UnitVector().Y(); + flowJacobian_(3, 3) = third * area.UnitVector().Z() * area.UnitVector().Z() + + 1.0; + flowJacobian_(4, 3) = fac * 0.5 * dist / (mu + mut) * tauNorm.Z() + + third * area.UnitVector().Z() * velNorm + state.W(); + + // assign column 4 + flowJacobian_(4, 4) = (eos.Conductivity(mu) + + eos.TurbConductivity(mut, turb->TurbPrandtlNumber())) + / ((mu + mut) * state.Rho()); + + flowJacobian_ *= area.Mag() * (mu + mut) / dist; fluxJacobian prim2Cons; prim2Cons.DelPrimativeDelConservative(state, eos, inp); - flowJacobian_ = flowJacobian_.MatMult(prim2Cons.flowJacobian_); // calculate turbulent jacobian if necessary if (inp.IsTurbulent()) { - turbJacobian_(0, 0) = mu + turb->SigmaK() * mut; - turbJacobian_(1, 1) = mu + turb->SigmaW() * mut; - turbJacobian_ *= 1.0 / dist; - - turbJacobian_ = turbJacobian_.MatMult(prim2Cons.turbJacobian_); + turbJacobian_ = fac * turb->ViscousJacobian(state, area, lamVisc, suth, + dist, turbVisc, f1); + // Don't need to multiply by prim2Cons b/c jacobian is already wrt + // conservative variables } } // non-member functions // ---------------------------------------------------------------------------- -// operator overload for << - allows use of cout, cerr, etc. -ostream &operator<<(ostream &os, fluxJacobian &jacobian) { +ostream &operator<<(ostream &os, const fluxJacobian &jacobian) { os << jacobian.FlowJacobian() << endl; os << jacobian.TurbulenceJacobian() << endl; return os; } - -genArray RusanovOffDiagonal(const primVars &state, const genArray &update, - const unitVec3dMag &fAreaL, - const unitVec3dMag &fAreaR, - const double &vol, const idealGas &eos, - const sutherland &suth, - const unique_ptr &turb, - const input &inp, const bool &positive) { +genArray RusanovScalarOffDiagonal(const primVars &state, + const genArray &update, + const unitVec3dMag &fArea, + const double &mu, + const double &mut, const double &f1, + const double &dist, + const idealGas &eos, const sutherland &suth, + const unique_ptr &turb, + const bool &isViscous, const bool &positive) { // state -- primative variables at off diagonal // update -- conserved variable update at off diagonal - // fAreaL -- face area vector on off diagonal boundary - // fAreaR -- face area vector opposite off diagonal boundary - // vol -- cell volume + // fArea -- face area vector on off diagonal boundary + // mu -- laminar viscosity + // mut -- turbulent viscosity + // f1 -- first blending coefficient + // dist -- distance from cell center to cell center across face on diagonal // eos -- equation of state // suth -- sutherland's law for viscosity // turb -- turbulence model - // inp -- input variables + // isViscous -- flag to determine if simulation is viscous // positive -- flag to determine whether to add or subtract dissipation // calculate updated state const auto stateUpdate = state.UpdateWithConsVars(eos, update, turb); // calculate updated convective flux - const auto fluxChange = ConvectiveFluxUpdate(state, stateUpdate, eos, - fAreaL.UnitVector()); - - // can't use stored cell spectral radius b/c it has contribuitons from i, j, k - const uncoupledScalar specRad(state.CellSpectralRadius(fAreaL, fAreaR, eos, - suth, vol, turb, - inp.IsViscous()), - turb->SpectralRadius(state, fAreaL, fAreaR, eos, - suth, vol, false)); + auto fluxChange = 0.5 * fArea.Mag() * + ConvectiveFluxUpdate(state, stateUpdate, eos, fArea.UnitVector()); + // zero out turbulence quantities b/c spectral radius is like full jacobian + fluxChange[5] = 0.0; + fluxChange[6] = 0.0; + + // can't use stored cell spectral radius b/c it has contributions from i, j, k + const uncoupledScalar specRad(state.FaceSpectralRadius(fArea, eos, + suth, dist, mu, mut, + turb, isViscous), + turb->FaceSpectralRadius(state, fArea, mu, suth, + dist, mut, f1, + positive)); return positive ? - 0.5 * (fAreaL.Mag() * fluxChange + specRad.ArrayMult(update)) : - 0.5 * (fAreaL.Mag() * fluxChange - specRad.ArrayMult(update)); + fluxChange + specRad.ArrayMult(update) : + fluxChange - specRad.ArrayMult(update); +} + +genArray RusanovBlockOffDiagonal(const primVars &state, + const genArray &update, + const unitVec3dMag &fArea, + const double &mu, + const double &mut, const double &f1, + const double &dist, + const idealGas &eos, const sutherland &suth, + const unique_ptr &turb, + const input &inp, const bool &positive, + const tensor &vGrad) { + // state -- primative variables at off diagonal + // update -- conserved variable update at off diagonal + // fArea -- face area vector on off diagonal boundary + // mu -- laminar viscosity + // mut -- turbulent viscosity + // f1 -- first blending coefficient + // dist -- distance from cell center to cell center across face on diagonal + // eos -- equation of state + // suth -- sutherland's law for viscosity + // turb -- turbulence model + // inp -- input variables + // positive -- flag to determine whether to add or subtract dissipation + // vGrad -- velocity gradient + + fluxJacobian jacobian(inp.NumFlowEquations(), inp.NumTurbEquations()); + + // calculate inviscid jacobian + jacobian.RusanovFluxJacobian(state, eos, fArea, positive, inp, turb); + + // add viscous contribution + if (inp.IsViscous()) { + fluxJacobian viscJac(inp.NumFlowEquations(), inp.NumTurbEquations()); + viscJac.ApproxTSLJacobian(state, mu, mut, f1, eos, suth, fArea, dist, turb, + inp, positive, vGrad); + positive ? jacobian -= viscJac : jacobian += viscJac; + } + return jacobian.ArrayMult(update); } -genArray RoeOffDiagonal(const primVars &left, const primVars &right, +genArray OffDiagonal(const primVars &offDiag, const primVars &diag, + const genArray &update, + const unitVec3dMag &fArea, const double &mu, + const double &mut, const double &f1, + const double &dist, const tensor &vGrad, + const idealGas &eos, const sutherland &suth, + const unique_ptr &turb, + const input &inp, const bool &positive) { + // offDiag -- primative variables at off diagonal + // diag -- primative variables at diagonal + // update -- conserved variable update at off diagonal + // fArea -- face area vector on off diagonal boundary + // mu -- laminar viscosity + // mut -- turbulent viscosity + // f1 -- first blending coefficient + // dist -- distance from cell center to cell center across face on diagonal + // vGrad -- velocity gradient + // eos -- equation of state + // suth -- sutherland's law for viscosity + // turb -- turbulence model + // input -- input variables + // positive -- flag to determine whether to add or subtract dissipation + + genArray offDiagonal(0.0); + + if (inp.InvFluxJac() == "rusanov") { + if (inp.IsBlockMatrix()) { + offDiagonal = RusanovBlockOffDiagonal(offDiag, update, fArea, mu, mut, f1, + dist, eos, suth, turb, inp, + positive, vGrad); + } else { + offDiagonal = RusanovScalarOffDiagonal(offDiag, update, fArea, mu, mut, + f1, dist, eos, suth, turb, + inp.IsViscous(), positive); + } + } else if (inp.InvFluxJac() == "approximateRoe") { + // always use flux change off diagonal with roe method + offDiagonal = RoeOffDiagonal(offDiag, diag, update, fArea, mu, mut, + f1, dist, eos, suth, turb, + inp.IsViscous(), inp.IsTurbulent(), + positive); + } else { + cerr << "ERROR: Error in OffDiagonal(), inviscid flux jacobian method of " + << inp.InvFluxJac() << " is not recognized!" << endl; + exit(EXIT_FAILURE); + } + + return offDiagonal; +} + + +genArray RoeOffDiagonal(const primVars &offDiag, const primVars &diag, const genArray &update, - const unitVec3dMag &fAreaL, - const unitVec3dMag &fAreaR, - const double &vol, const idealGas &eos, + const unitVec3dMag &fArea, + const double &mu, const double &mut, + const double &dist, const double &f1, + const idealGas &eos, const sutherland &suth, const unique_ptr &turb, - const input &inp, const bool &positive) { - // left -- primative variables at left side - // right -- primative variables at right side + const bool &isViscous, const bool &isTurbulent, + const bool &positive) { + // offDiag -- primative variables at off diagonal + // diag -- primative variables at diagonal // update -- conserved variable update at off diagonal - // fAreaL -- face area vector on off diagonal boundary - // fAreaR -- face area vector opposite off diagonal boundary - // vol -- cell volume + // fArea -- face area vector on off diagonal boundary + // dist -- distance from cell center to cell center + // mu -- laminar viscosity at off diagonal + // mut -- turbulent viscosity at off diagonal + // f1 -- first blending coefficient at off diagonal // eos -- equation of state // suth -- sutherland's law for viscosity // turb -- turbulence model - // inp -- input variables + // isViscous -- flag to determine if simulation is viscous + // isTurbulent -- flag to determine if simulation is turbulent // positive -- flag to determine whether to add or subtract dissipation - const auto areaNorm = fAreaL.UnitVector(); + // DEBUG -- redo this whole function to not use the flux change and instead + // calculate the matrix jacobian and multiply with the update + + const auto areaNorm = fArea.UnitVector(); // calculate Roe flux with old variables - const auto oldFlux = RoeFlux(left, right, eos, areaNorm); + const auto oldFlux = RoeFlux(offDiag, diag, eos, areaNorm); - // calculate updated Roe flux - const auto stateUpdate = positive ? - left.UpdateWithConsVars(eos, update, turb) : - right.UpdateWithConsVars(eos, update, turb); + // calculate updated Roe flux on off diagonal + const auto stateUpdate = offDiag.UpdateWithConsVars(eos, update, turb); const auto newFlux = positive ? - RoeFlux(stateUpdate, right, eos, areaNorm) : - RoeFlux(left, stateUpdate, eos, areaNorm); + RoeFlux(stateUpdate, diag, eos, areaNorm) : + RoeFlux(diag, stateUpdate, eos, areaNorm); + // don't need 0.5 factor on roe flux because RoeFlux function already does it + const auto fluxChange = fArea.Mag() * (newFlux - oldFlux).ConvertToGenArray(); + // add contribution for viscous terms uncoupledScalar specRad(0.0, 0.0); - if (inp.IsViscous()) { - const auto offState = positive ? left : right; - + if (isViscous) { specRad.AddToFlowVariable( - offState.ViscCellSpectralRadius(fAreaL, fAreaR, eos, suth, vol, turb)); + offDiag.ViscFaceSpectralRadius(fArea, eos, suth, dist, mu, + mut, turb)); - if (inp.IsTurbulent()) { - specRad.AddToTurbVariable(turb->ViscSpecRad(offState, fAreaL, fAreaR, eos, - suth, vol)); + if (isTurbulent) { + specRad.AddToTurbVariable(turb->ViscFaceSpecRad(offDiag, fArea, mu, suth, + dist, mut, f1)); } } - // don't need 0.5 factor on roe flux because RoeFlux function already does it - return positive ? - fAreaL.Mag() * ((newFlux - oldFlux).ConvertToGenArray()) + - 0.5 * specRad.ArrayMult(update) : - fAreaL.Mag() * ((newFlux - oldFlux).ConvertToGenArray()) - - 0.5 * specRad.ArrayMult(update); + return positive ? fluxChange + specRad.ArrayMult(update) : + fluxChange - specRad.ArrayMult(update); } +void fluxJacobian::MultiplyOnDiagonal(const double &val, + const bool &isTurbulent) { + // val -- value to multiply along diagonal + // isTurbulent -- flag identifiying if simulation is turbulent + + for (auto ii = 0; ii < flowJacobian_.Size(); ii++) { + flowJacobian_(ii, ii) *= val; + } + + if (isTurbulent) { + for (auto ii = 0; ii < turbJacobian_.Size(); ii++) { + turbJacobian_(ii, ii) *= val; + } + } +} + +void fluxJacobian::AddOnDiagonal(const double &val, const bool &isTurbulent) { + // val -- value to multiply along diagonal + // isTurbulent -- flag identifiying if simulation is turbulent + + for (auto ii = 0; ii < flowJacobian_.Size(); ii++) { + flowJacobian_(ii, ii) += val; + } + + if (isTurbulent) { + for (auto ii = 0; ii < turbJacobian_.Size(); ii++) { + turbJacobian_(ii, ii) += val; + } + } +} diff --git a/fluxJacobian.hpp b/fluxJacobian.hpp index 97e9ad6..004a896 100644 --- a/fluxJacobian.hpp +++ b/fluxJacobian.hpp @@ -18,21 +18,16 @@ // execute these lines of code #define FLUXJACOBIANHEADERDEF // define the macro -#include // cout #include // vector -#include // string #include // unique_ptr #include "vector3d.hpp" +#include "tensor.hpp" #include "uncoupledScalar.hpp" #include "matrix.hpp" using std::vector; -using std::string; -using std::cout; -using std::endl; -using std::cerr; using std::ostream; -using std:: unique_ptr; +using std::unique_ptr; // forward class declarations class primVars; @@ -53,6 +48,8 @@ class fluxJacobian { // constructors fluxJacobian(const double &flow, const double &turb); fluxJacobian(const int &flowSize, const int &turbSize); + fluxJacobian(const squareMatrix &flow, const squareMatrix &turb) + : flowJacobian_(flow), turbJacobian_(turb) {} fluxJacobian() : fluxJacobian(0.0, 0.0) {} explicit fluxJacobian(const uncoupledScalar &specRad) : fluxJacobian(specRad.FlowVariable(), specRad.TurbVariable()) {} @@ -66,29 +63,37 @@ class fluxJacobian { fluxJacobian& operator=(const fluxJacobian&) = default; // member functions - squareMatrix FlowJacobian() const { return flowJacobian_; } - squareMatrix TurbulenceJacobian() const { return turbJacobian_; } + squareMatrix FlowJacobian() const {return flowJacobian_;} + squareMatrix TurbulenceJacobian() const {return turbJacobian_;} void AddToFlowJacobian(const squareMatrix &jac) {flowJacobian_ += jac;} void AddToTurbJacobian(const squareMatrix &jac) {turbJacobian_ += jac;} void SubtractFromFlowJacobian(const squareMatrix &jac) {flowJacobian_ -= jac;} void SubtractFromTurbJacobian(const squareMatrix &jac) {turbJacobian_ -= jac;} - void RusanovFluxJacobian(const primVars &, const primVars &, - const idealGas &, const vector3d &, - const bool &, const input &); + void MultiplyOnDiagonal(const double &, const bool &); + void AddOnDiagonal(const double &, const bool &); + + void RusanovFluxJacobian(const primVars &, const idealGas &, + const unitVec3dMag &, + const bool &, const input &, + const unique_ptr &); void InvFluxJacobian(const primVars &, const idealGas &, - const vector3d &, const input &); + const unitVec3dMag &, const input &, + const unique_ptr &); void ApproxRoeFluxJacobian(const primVars &, const primVars &, - const idealGas &, const vector3d &, - const bool &, const input &); + const idealGas &, const unitVec3dMag &, + const bool &, const input &, + const unique_ptr &); void DelPrimativeDelConservative(const primVars &, const idealGas &, const input &); - void ApproxTSLJacobian(const primVars &, const idealGas &, + void ApproxTSLJacobian(const primVars &, const double &, const double &, + const double &, const idealGas &, const sutherland &, - const vector3d &, const double &, - const unique_ptr &, const input &); + const unitVec3dMag &, const double &, + const unique_ptr &, const input &, + const bool &, const tensor &); void Zero() { flowJacobian_.Zero(); @@ -230,21 +235,41 @@ inline const fluxJacobian operator/(const double &lhs, fluxJacobian rhs) { return rhs; } -ostream &operator<<(ostream &os, const fluxJacobian &); - -genArray RusanovOffDiagonal(const primVars &, const genArray &, - const unitVec3dMag &, - const unitVec3dMag &, - const double &, const idealGas &, - const sutherland &, - const unique_ptr &, - const input &, const bool &); -genArray RoeOffDiagonal(const primVars &, const primVars &, const genArray &, - const unitVec3dMag &, - const unitVec3dMag &, - const double &, const idealGas &, const sutherland &, - const unique_ptr &, const input &, - const bool &); +ostream &operator<<(ostream &os, const fluxJacobian &jacobian); + +genArray RusanovScalarOffDiagonal(const primVars &, const genArray &, + const unitVec3dMag &, + const double &, const double &, + const double &, const double &, + const idealGas &, + const sutherland &, + const unique_ptr &, + const bool &, const bool &); +genArray RusanovBlockOffDiagonal(const primVars &, const genArray &, + const unitVec3dMag &, + const double &, const double &, + const double &, const double &, + const idealGas &, + const sutherland &, + const unique_ptr &, + const input &, const bool &, + const tensor &); + +genArray RoeOffDiagonal(const primVars &, const primVars &, + const genArray &, + const unitVec3dMag &, const double &, + const double &, const double &, + const double &, const idealGas &, + const sutherland &, + const unique_ptr &, const bool &, + const bool &, const bool &); + +genArray OffDiagonal(const primVars &, const primVars &, const genArray &, + const unitVec3dMag &, const double &, + const double &, const double &, const double &, + const tensor &, const idealGas &, + const sutherland &, const unique_ptr &, + const input &, const bool &); #endif diff --git a/genArray.hpp b/genArray.hpp index b68d128..27ab76c 100644 --- a/genArray.hpp +++ b/genArray.hpp @@ -43,7 +43,7 @@ class genArray { genArray() : genArray(0.0, 0.0, 0.0, 0.0, 0.0) {} explicit genArray(const double &a) : genArray(a, a, a, a, a, a, a) {} explicit genArray(const uncoupledScalar &a); - + // member functions void Zero(); double Sum(); diff --git a/gradients.cpp b/gradients.cpp deleted file mode 100644 index 6259739..0000000 --- a/gradients.cpp +++ /dev/null @@ -1,212 +0,0 @@ -/* This file is part of aither. - Copyright (C) 2015 Michael Nucci (michael.nucci@gmail.com) - - Aither 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. - - Aither 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 this program. If not, see . */ - -#include -#include -#include -#include "gradients.hpp" -#include "procBlock.hpp" -#include "eos.hpp" - -using std::cout; -using std::endl; -using std::cerr; -using std::string; - -// constructor -gradients::gradients() { - // default to 1 faces - velocityI_ = multiArray3d>(1, 1, 1); - velocityJ_ = multiArray3d>(1, 1, 1); - velocityK_ = multiArray3d>(1, 1, 1); - - temperatureI_ = multiArray3d>(1, 1, 1); - temperatureJ_ = multiArray3d>(1, 1, 1); - temperatureK_ = multiArray3d>(1, 1, 1); - - tkeI_ = multiArray3d>(1, 1, 1); - tkeJ_ = multiArray3d>(1, 1, 1); - tkeK_ = multiArray3d>(1, 1, 1); - - omegaI_ = multiArray3d>(1, 1, 1); - omegaJ_ = multiArray3d>(1, 1, 1); - omegaK_ = multiArray3d>(1, 1, 1); -} - -// alternate constructor to calculate gradients from state variables -gradients::gradients(const bool &turbFlag, const procBlock &blk, - const idealGas &eos) { - // turbFlag -- flag to determine if simulation is turbulent and therefore - // requires tke and omega gradients - // blk -- procBlock to calculate gradients for - // eos -- equation of state - - // size vectors for input procBlock - velocityI_ = multiArray3d>(blk.NumI() + 1, blk.NumJ(), - blk.NumK()); - velocityJ_ = multiArray3d>(blk.NumI(), blk.NumJ() + 1, - blk.NumK()); - velocityK_ = multiArray3d>(blk.NumI(), blk.NumJ(), - blk.NumK() + 1); - - temperatureI_ = multiArray3d>(blk.NumI() + 1, - blk.NumJ(), blk.NumK()); - temperatureJ_ = multiArray3d>(blk.NumI(), blk.NumJ() + 1, - blk.NumK()); - temperatureK_ = multiArray3d>(blk.NumI(), blk.NumJ(), - blk.NumK() + 1); - - // if flow is not turbulent, don't need tke and omega gradients so they can be - // set to a minimum size - if (turbFlag) { - tkeI_ = multiArray3d>(blk.NumI() + 1, blk.NumJ(), - blk.NumK()); - tkeJ_ = multiArray3d>(blk.NumI(), blk.NumJ() + 1, - blk.NumK()); - tkeK_ = multiArray3d>(blk.NumI(), blk.NumJ(), - blk.NumK() + 1); - - omegaI_ = multiArray3d>(blk.NumI() + 1, blk.NumJ(), - blk.NumK()); - omegaJ_ = multiArray3d>(blk.NumI(), blk.NumJ() + 1, - blk.NumK()); - omegaK_ = multiArray3d>(blk.NumI(), blk.NumJ(), - blk.NumK() + 1); - } else { - tkeI_ = multiArray3d>(1, 1, 1); - tkeJ_ = multiArray3d>(1, 1, 1); - tkeK_ = multiArray3d>(1, 1, 1); - - omegaI_ = multiArray3d>(1, 1, 1); - omegaJ_ = multiArray3d>(1, 1, 1); - omegaK_ = multiArray3d>(1, 1, 1); - } - - // loop over i-faces and calculate gradients - // loop over all physical faces - for (auto kk = 0; kk < blk.NumK(); kk++) { - for (auto jj = 0; jj < blk.NumJ(); jj++) { - for (auto ii = 0; ii < blk.NumI() + 1; ii++) { - if (turbFlag) { - blk.CalcGradsI(ii + blk.NumGhosts(), jj + blk.NumGhosts(), - kk + blk.NumGhosts(), eos, turbFlag, - velocityI_(ii, jj, kk), temperatureI_(ii, jj, kk), - tkeI_(ii, jj, kk), omegaI_(ii, jj, kk)); - } else { - vector3d dum1, dum2; - blk.CalcGradsI(ii + blk.NumGhosts(), jj + blk.NumGhosts(), - kk + blk.NumGhosts(), eos, turbFlag, - velocityI_(ii, jj, kk), temperatureI_(ii, jj, kk), - dum1, dum2); - } - } - } - } - - // loop over j-faces and calculate gradients - // loop over all physical faces - for (auto kk = 0; kk < blk.NumK(); kk++) { - for (auto jj = 0; jj < blk.NumJ() + 1; jj++) { - for (auto ii = 0; ii < blk.NumI(); ii++) { - // get face location - if (turbFlag) { - blk.CalcGradsJ(ii + blk.NumGhosts(), jj + blk.NumGhosts(), - kk + blk.NumGhosts(), eos, turbFlag, - velocityJ_(ii, jj, kk), temperatureJ_(ii, jj, kk), - tkeJ_(ii, jj, kk), omegaJ_(ii, jj, kk)); - } else { - vector3d dum1, dum2; - blk.CalcGradsJ(ii + blk.NumGhosts(), jj + blk.NumGhosts(), - kk + blk.NumGhosts(), eos, turbFlag, - velocityJ_(ii, jj, kk), temperatureJ_(ii, jj, kk), - dum1, dum2); - } - } - } - } - - // loop over k-faces and calculate gradients - // loop over all physical faces - for (auto kk = 0; kk < blk.NumK() + 1; kk++) { - for (auto jj = 0; jj < blk.NumJ(); jj++) { - for (auto ii = 0; ii < blk.NumI(); ii++) { - if (turbFlag) { - blk.CalcGradsK(ii + blk.NumGhosts(), jj + blk.NumGhosts(), - kk + blk.NumGhosts(), eos, turbFlag, - velocityK_(ii, jj, kk), temperatureK_(ii, jj, kk), - tkeK_(ii, jj, kk), omegaK_(ii, jj, kk)); - } else { - vector3d dum1, dum2; - blk.CalcGradsK(ii + blk.NumGhosts(), jj + blk.NumGhosts(), - kk + blk.NumGhosts(), eos, turbFlag, - velocityK_(ii, jj, kk), temperatureK_(ii, jj, kk), - dum1, dum2); - } - } - } - } -} - -// member function to calculate velocity gradient at cell center -tensor gradients::VelGradCell(const int &ii, const int &jj, - const int &kk) const { - // ii - i dimension of cell to get gradient at - // jj - j dimension of cell to get gradient at - // kk - k dimension of cell to get gradient at - - return (1.0 / 6.0) * (velocityI_(ii, jj, kk) + velocityI_(ii + 1, jj, kk) + - velocityJ_(ii, jj, kk) + velocityJ_(ii, jj + 1, kk) + - velocityK_(ii, jj, kk) + velocityK_(ii, jj, kk + 1)); -} - -// member function to calculate temperature gradient at cell center -vector3d gradients::TempGradCell(const int &ii, const int &jj, - const int &kk) const { - // ii - i dimension of cell to get gradient at - // jj - j dimension of cell to get gradient at - // kk - k dimension of cell to get gradient at - - return (1.0 / 6.0) * (temperatureI_(ii, jj, kk) + - temperatureI_(ii + 1, jj, kk) + - temperatureJ_(ii, jj, kk) + - temperatureJ_(ii, jj + 1, kk) + - temperatureK_(ii, jj, kk) + - temperatureK_(ii, jj, kk + 1)); -} - -// member function to calculate tke gradient at cell center -vector3d gradients::TkeGradCell(const int &ii, const int &jj, - const int &kk) const { - // ii - i dimension of cell to get gradient at - // jj - j dimension of cell to get gradient at - // kk - k dimension of cell to get gradient at - - return (1.0 / 6.0) * (tkeI_(ii, jj, kk) + tkeI_(ii + 1, jj, kk) + - tkeJ_(ii, jj, kk) + tkeJ_(ii, jj + 1, kk) + - tkeK_(ii, jj, kk) + tkeK_(ii, jj, kk + 1)); -} - -// member function to calculate omega gradient at cell center -vector3d gradients::OmegaGradCell(const int &ii, const int &jj, - const int &kk) const { - // ii - i dimension of cell to get gradient at - // jj - j dimension of cell to get gradient at - // kk - k dimension of cell to get gradient at - - return (1.0 / 6.0) * (omegaI_(ii, jj, kk) + omegaI_(ii + 1, jj, kk) + - omegaJ_(ii, jj, kk) + omegaJ_(ii, jj + 1, kk) + - omegaK_(ii, jj, kk) + omegaK_(ii, jj, kk + 1)); -} diff --git a/gradients.hpp b/gradients.hpp deleted file mode 100644 index dc89843..0000000 --- a/gradients.hpp +++ /dev/null @@ -1,134 +0,0 @@ -/* This file is part of aither. - Copyright (C) 2015 Michael Nucci (michael.nucci@gmail.com) - - Aither 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. - - Aither 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 this program. If not, see . */ - -#ifndef GRADIENTSHEADERDEF // only if the macro GRADIENTSHEADERDEF is not - // defined execute these lines of code -#define GRADIENTSHEADERDEF // define the macro - -/* This header contains the gradients class. - - The gradients class stores the gradient terms for the inviscid fluxes - viscous fluxes, and source terms. */ - -#include // vector -#include -#include "vector3d.hpp" -#include "tensor.hpp" -#include "multiArray3d.hpp" - -using std::cout; -using std::endl; -using std::cerr; - -// forward class declarations -class procBlock; -class idealGas; - -class gradients { - // velocity gradients at cell faces - multiArray3d> velocityI_; - multiArray3d> velocityJ_; - multiArray3d> velocityK_; - - // temperature gradients at cell faces - multiArray3d> temperatureI_; - multiArray3d> temperatureJ_; - multiArray3d> temperatureK_; - - // tke gradients at cell faces - multiArray3d> tkeI_; - multiArray3d> tkeJ_; - multiArray3d> tkeK_; - - // omega gradients at cell faces - multiArray3d> omegaI_; - multiArray3d> omegaJ_; - multiArray3d> omegaK_; - - public: - // constructors - gradients(); - gradients(const bool &, const procBlock &, const idealGas &); - - // move constructor and assignment operator - gradients(gradients&&) noexcept = default; - gradients& operator=(gradients&&) noexcept = default; - - // copy constructor and assignment operator - gradients(const gradients&) = default; - gradients& operator=(const gradients&) = default; - - // member functions - tensor VelGradI(const int &ii, const int &jj, const int &kk) const { - return velocityI_(ii, jj, kk); - } - tensor VelGradJ(const int &ii, const int &jj, const int &kk) const { - return velocityJ_(ii, jj, kk); - } - tensor VelGradK(const int &ii, const int &jj, const int &kk) const { - return velocityK_(ii, jj, kk); - } - vector3d TempGradI(const int &ii, const int &jj, - const int &kk) const { - return temperatureI_(ii, jj, kk); - } - vector3d TempGradJ(const int &ii, const int &jj, - const int &kk) const { - return temperatureJ_(ii, jj, kk); - } - vector3d TempGradK(const int &ii, const int &jj, - const int &kk) const { - return temperatureK_(ii, jj, kk); - } - vector3d TkeGradI(const int &ii, const int &jj, const int &kk) const { - return tkeI_(ii, jj, kk); - } - vector3d TkeGradJ(const int &ii, const int &jj, const int &kk) const { - return tkeJ_(ii, jj, kk); - } - vector3d TkeGradK(const int &ii, const int &jj, const int &kk) const { - return tkeK_(ii, jj, kk); - } - vector3d OmegaGradI(const int &ii, const int &jj, - const int &kk) const { - return omegaI_(ii, jj, kk); - } - vector3d OmegaGradJ(const int &ii, const int &jj, - const int &kk) const { - return omegaJ_(ii, jj, kk); - } - vector3d OmegaGradK(const int &ii, const int &jj, - const int &kk) const { - return omegaK_(ii, jj, kk); - } - - // functions to get number of cells in block - int NumI() const { return velocityI_.NumI() - 1; } - int NumJ() const { return velocityI_.NumJ(); } - int NumK() const { return velocityI_.NumK(); } - - tensor VelGradCell(const int &, const int &, const int &) const; - vector3d TempGradCell(const int &, const int &, const int &) const; - vector3d TkeGradCell(const int &, const int &, const int &) const; - vector3d OmegaGradCell(const int &, const int &, const int &) const; - - // destructor - ~gradients() noexcept {} -}; - -// function definitions - -#endif diff --git a/input.cpp b/input.cpp index 09aa41b..f6087c8 100644 --- a/input.cpp +++ b/input.cpp @@ -14,14 +14,15 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -#include // timing capability -#include // cout -#include // put_time -#include // ifstream -#include // exit() -#include // istringstream -#include // istring_iterator -#include // make_unique +#include // timing capability +#include // cout +#include // put_time +#include // ifstream +#include // exit() +#include // istringstream +#include // istring_iterator +#include // make_unique +#include // min #include #include #include "input.hpp" @@ -41,7 +42,7 @@ using std::stod; // constructor for input class // initialize vector to have length of number of acceptable inputs to the code -input::input(const string &name) : simName_(name), vars_(35) { +input::input(const string &name) : simName_(name) { // default values for each variable gName_ = ""; dt_ = -1.0; @@ -51,11 +52,8 @@ input::input(const string &name) : simName_(name), vars_(35) { lRef_ = 1.0; gamma_ = 1.4; gasConst_ = 287.058; - velRef_.SetX(1.0); - velRef_.SetY(0.0); - velRef_.SetZ(0.0); - vector dummy(1); - bc_ = dummy; + velRef_ = {1.0, 0.0, 0.0}; + bc_ = vector(1); timeIntegration_ = "explicitEuler"; cfl_ = -1.0; kappa_ = -2.0; // default to value outside of range to tell if higher @@ -92,45 +90,44 @@ input::input(const string &name) : simName_(name), vars_(35) { farfieldTurbInten_ = 0.01; farfieldEddyViscRatio_ = 10.0; + // default to primative variables + outputVariables_ = {"density", "vel_x", "vel_y", "vel_z", "pressure"}; + // keywords in the input file that the parser is looking for to define // variables - vars_[0] = "gridName:"; - vars_[1] = "timeStep:"; - vars_[2] = "iterations:"; - vars_[3] = "pressureRef:"; - vars_[4] = "densityRef:"; - vars_[5] = "lengthRef:"; - vars_[6] = "gamma:"; - vars_[7] = "gasConstant:"; - vars_[8] = "velocity:"; - vars_[9] = "timeIntegration:"; - vars_[10] = "cfl:"; - vars_[11] = "faceReconstruction:"; - vars_[12] = "limiter:"; - vars_[13] = "outputFrequency:"; - vars_[14] = "equationSet:"; - vars_[15] = "temperatureRef:"; - vars_[16] = "matrixSolver:"; - vars_[17] = "matrixSweeps:"; - vars_[18] = "matrixRelaxation:"; - vars_[19] = "timeIntTheta:"; - vars_[20] = "timeIntZeta:"; - vars_[21] = "nonlinearIterations:"; - vars_[22] = "cflMax:"; - vars_[23] = "cflStep:"; - vars_[24] = "cflStart:"; - vars_[25] = "inviscidFluxJacobian:"; - vars_[26] = "dualTimeCFL:"; - vars_[27] = "inviscidFlux:"; - vars_[28] = "stagnationInlet:"; - vars_[29] = "pressureOutlet:"; - vars_[30] = "decompositionMethod:"; - vars_[31] = "turbulenceModel:"; - vars_[32] = "farfieldTurbulenceIntensity:"; - vars_[33] = "farfieldEddyViscosityRatio:"; - - // boundary conditions should be listed last - vars_[vars_.size() - 1] = "boundaryConditions:"; + vars_ = {"gridName:", + "timeStep:", + "iterations:", + "pressureRef:", + "densityRef:", + "lengthRef:", + "gamma:", + "gasConstant:", + "velocity:", + "timeIntegration:", + "faceReconstruction:", + "limiter:", + "outputFrequency:", + "equationSet:", + "temperatureRef:", + "matrixSolver:", + "matrixSweeps:", + "matrixRelaxation:", + "nonlinearIterations:", + "cflMax:", + "cflStep:", + "cflStart:", + "inviscidFluxJacobian:", + "dualTimeCFL:", + "inviscidFlux:", + "stagnationInlet:", + "pressureOutlet:", + "decompositionMethod:", + "turbulenceModel:", + "farfieldTurbulenceIntensity:", + "farfieldEddyViscosityRatio:", + "outputVariables:", + "boundaryConditions:"}; } // function to trim leading and trailing whitespace from a string, and also @@ -158,8 +155,8 @@ string trim(const string &s, const string &whitespace = " \t") { // function to print the time void PrintTime() { - auto now = std::chrono::high_resolution_clock::now(); - auto nowOut = std::chrono::high_resolution_clock::to_time_t(now); + auto now = std::chrono::system_clock::now(); + auto nowOut = std::chrono::system_clock::to_time_t(now); cout << std::put_time(std::localtime(&nowOut), "%c") << endl; } @@ -183,11 +180,10 @@ void input::ReadInput(const int &rank) { if (inFile.fail()) { cerr << "ERROR: Error in input::ReadInput(). Input file " << simName_ << " did not open correctly!!!" << endl; - exit(0); + exit(EXIT_FAILURE); } string line = ""; - vector3d temp; auto readingBCs = 0; auto blk = 0; auto surfCounter = 0; @@ -210,322 +206,293 @@ void input::ReadInput(const int &rank) { // search to see if first token corresponds to any keywords // line must contain at least 2 tokens (keyword and value) if (tokens.size() >= 2) { - for (auto ii = 0; ii < this->NumVars(); - ii++) { // loop over all input variables and see if they match - // keywords - - if (tokens[0] == this->Vars(ii) || - readingBCs > 0) { // if first token matches a keyword or reading - // boundary conditions - - // if not yet reading BCs (readingBCs == 0), set variable in input - // class to corresponding value and print assignment to std out - if (ii == 0 && readingBCs == 0) { - gName_ = tokens[1]; - if (rank == ROOTP) { - cout << this->Vars(ii) << " " << this->GridName() << endl; - } - continue; - } else if (ii == 1 && readingBCs == 0) { - dt_ = stod(tokens[1]); // double variable (stod) - if (rank == ROOTP) { - cout << this->Vars(ii) << " " << this->Dt() << endl; - } - continue; - } else if (ii == 2 && readingBCs == 0) { - iterations_ = stoi(tokens[1]); - if (rank == ROOTP) { - cout << this->Vars(ii) << " " << this->Iterations() << endl; - } - continue; - } else if (ii == 3 && readingBCs == 0) { - pRef_ = stod(tokens[1]); // double variable (stod) - if (rank == ROOTP) { - cout << this->Vars(ii) << " " << this->PRef() << endl; - } - continue; - } else if (ii == 4 && readingBCs == 0) { - rRef_ = stod(tokens[1]); // double variable (stod) - if (rank == ROOTP) { - cout << this->Vars(ii) << " " << this->RRef() << endl; - } - continue; - } else if (ii == 5 && readingBCs == 0) { - lRef_ = stod(tokens[1]); // double variable (stod) - if (rank == ROOTP) { - cout << this->Vars(ii) << " " << this->LRef() << endl; - } - continue; - } else if (ii == 6 && readingBCs == 0) { - gamma_ = stod(tokens[1]); // double variable (stod) - if (rank == ROOTP) { - cout << this->Vars(ii) << " " << this->Gamma() << endl; - } - continue; - } else if (ii == 7 && readingBCs == 0) { - gasConst_ = stod(tokens[1]); // double variable (stod) - if (rank == ROOTP) { - cout << this->Vars(ii) << " " << this->R() << endl; - } - continue; - } else if (ii == 8 && readingBCs == 0) { - temp.SetX(stod(tokens[1])); // double variable (stod) - temp.SetY(stod(tokens[2])); - temp.SetZ(stod(tokens[3])); - velRef_ = temp; - if (rank == ROOTP) { - cout << this->Vars(ii) << " " << this->VelRef() << endl; - } - continue; - } else if (ii == 9 && readingBCs == 0) { - timeIntegration_ = tokens[1]; - if (this->TimeIntegration() == "implicitEuler") { - timeIntTheta_ = 1.0; - timeIntZeta_ = 0.0; - } else if (this->TimeIntegration() == "crankNicholson") { - timeIntTheta_ = 0.5; - timeIntZeta_ = 0.0; - } else if (this->TimeIntegration() == "bdf2") { - timeIntTheta_ = 1.0; - timeIntZeta_ = 0.5; - } + auto key = tokens[0]; + // if first token matches a keyword or reading boundary condtions + if (vars_.find(key) != vars_.end() || readingBCs > 0) { + // if not yet reading BCs (readingBCs == 0), set variable in input + // class to corresponding value and print assignment to std out + if (key == "gridName:") { + gName_ = tokens[1]; + if (rank == ROOTP) { + cout << key << " " << this->GridName() << endl; + } + } else if (key == "timeStep:") { + dt_ = stod(tokens[1]); // double variable (stod) + if (rank == ROOTP) { + cout << key << " " << this->Dt() << endl; + } + } else if (key == "iterations:") { + iterations_ = stoi(tokens[1]); + if (rank == ROOTP) { + cout << key << " " << this->Iterations() << endl; + } + } else if (key == "pressureRef:") { + pRef_ = stod(tokens[1]); // double variable (stod) + if (rank == ROOTP) { + cout << key << " " << this->PRef() << endl; + } + } else if (key == "densityRef:") { + rRef_ = stod(tokens[1]); // double variable (stod) + if (rank == ROOTP) { + cout << key << " " << this->RRef() << endl; + } + } else if (key == "lengthRef:") { + lRef_ = stod(tokens[1]); // double variable (stod) + if (rank == ROOTP) { + cout << key << " " << this->LRef() << endl; + } + } else if (key == "gamma:") { + gamma_ = stod(tokens[1]); // double variable (stod) + if (rank == ROOTP) { + cout << key << " " << this->Gamma() << endl; + } + } else if (key == "gasConstant:") { + gasConst_ = stod(tokens[1]); // double variable (stod) + if (rank == ROOTP) { + cout << key << " " << this->R() << endl; + } + } else if (key == "velocity:") { + velRef_.SetX(stod(tokens[1])); // double variable (stod) + velRef_.SetY(stod(tokens[2])); + velRef_.SetZ(stod(tokens[3])); + if (rank == ROOTP) { + cout << key << " " << this->VelRef() << endl; + } + } else if (key == "timeIntegration:") { + timeIntegration_ = tokens[1]; + if (this->TimeIntegration() == "implicitEuler") { + timeIntTheta_ = 1.0; + timeIntZeta_ = 0.0; + } else if (this->TimeIntegration() == "crankNicholson") { + timeIntTheta_ = 0.5; + timeIntZeta_ = 0.0; + } else if (this->TimeIntegration() == "bdf2") { + timeIntTheta_ = 1.0; + timeIntZeta_ = 0.5; + } - if (rank == ROOTP) { - cout << this->Vars(ii) << " " << this->TimeIntegration() - << endl; - } - continue; - } else if (ii == 11 && readingBCs == 0) { - if (tokens[1] == "upwind") { - kappa_ = -1.0; - } else if (tokens[1] == "fromm") { - kappa_ = 0.0; - } else if (tokens[1] == "quick") { - kappa_ = 0.5; - } else if (tokens[1] == "central") { - kappa_ = 1.0; - } else if (tokens[1] == "thirdOrder") { - kappa_ = 1.0 / 3.0; - } else if (tokens[1] == "constant") { - kappa_ = -2.0; - } else { - // if string is not recognized, set kappa to number input - kappa_ = stod(tokens[1]); - } + if (rank == ROOTP) { + cout << key << " " << this->TimeIntegration() << endl; + } + } else if (key == "faceReconstruction:") { + if (tokens[1] == "upwind") { + kappa_ = -1.0; + } else if (tokens[1] == "fromm") { + kappa_ = 0.0; + } else if (tokens[1] == "quick") { + kappa_ = 0.5; + } else if (tokens[1] == "central") { + kappa_ = 1.0; + } else if (tokens[1] == "thirdOrder") { + kappa_ = 1.0 / 3.0; + } else if (tokens[1] == "constant") { + kappa_ = -2.0; + } else { + // if string is not recognized, set kappa to number input + kappa_ = stod(tokens[1]); + } - if (rank == ROOTP) { - cout << this->Vars(ii) << " " << tokens[1] - << " kappa = " << this->Kappa() << endl; - } - if ((this->Kappa() < -1.0) || (this->Kappa() > 1.0)) { - cerr << "ERROR: Error in input::ReadInput(). Kappa value of " - << this->Kappa() - << " is not valid! Choose a value between -1.0 and 1.0." - << endl; - exit(0); - } - continue; - } else if (ii == 12 && readingBCs == 0) { - limiter_ = tokens[1]; - if (rank == ROOTP) { - cout << this->Vars(ii) << " " << this->Limiter() << endl; - } - continue; - } else if (ii == 13 && readingBCs == 0) { - outputFrequency_ = stoi(tokens[1]); - if (rank == ROOTP) { - cout << this->Vars(ii) << " " << this->OutputFrequency() - << endl; - } - continue; - } else if (ii == 14 && readingBCs == 0) { - equationSet_ = tokens[1]; - if (rank == ROOTP) { - cout << this->Vars(ii) << " " << this->EquationSet() << endl; - } - continue; - } else if (ii == 15 && readingBCs == 0) { - tRef_ = stod(tokens[1]); // double variable (stod) - if (rank == ROOTP) { - cout << this->Vars(ii) << " " << this->TRef() << endl; - } - continue; - } else if (ii == 16 && readingBCs == 0) { - matrixSolver_ = tokens[1]; - if (rank == ROOTP) { - cout << this->Vars(ii) << " " << this->MatrixSolver() << endl; - } - continue; - } else if (ii == 17 && readingBCs == 0) { - matrixSweeps_ = stoi(tokens[1]); - if (rank == ROOTP) { - cout << this->Vars(ii) << " " << this->MatrixSweeps() << endl; - } - continue; - } else if (ii == 18 && readingBCs == 0) { - matrixRelaxation_ = - stod(tokens[1]); // double variable (stod) - if (rank == ROOTP) { - cout << this->Vars(ii) << " " << this->MatrixRelaxation() - << endl; - } - continue; - } else if (ii == 21 && readingBCs == 0) { - nonlinearIterations_ = stoi(tokens[1]); - if (rank == ROOTP) { - cout << this->Vars(ii) << " " << this->NonlinearIterations() - << endl; - } - continue; - } else if (ii == 22 && readingBCs == 0) { - cflMax_ = stod(tokens[1]); // double (stod) - if (rank == ROOTP) { - cout << this->Vars(ii) << " " << this->CFLMax() << endl; - } - continue; - } else if (ii == 23 && readingBCs == 0) { - cflStep_ = stod(tokens[1]); // double (stod) - if (rank == ROOTP) { - cout << this->Vars(ii) << " " << this->CFLStep() << endl; - } - continue; - } else if (ii == 24 && readingBCs == 0) { - cflStart_ = stod(tokens[1]); // double variable (stod) - if (rank == ROOTP) { - cout << this->Vars(ii) << " " << this->CFLStart() << endl; - } - continue; - } else if (ii == 25 && readingBCs == 0) { - invFluxJac_ = tokens[1]; - if (rank == ROOTP) { - cout << this->Vars(ii) << " " << this->InvFluxJac() << endl; - } - } else if (ii == 26 && readingBCs == 0) { - dualTimeCFL_ = stod(tokens[1]); // double variable (stod) - if (rank == ROOTP) { - cout << this->Vars(ii) << " " << this->DualTimeCFL() << endl; - } - continue; - } else if (ii == 27 && readingBCs == 0) { - inviscidFlux_ = tokens[1]; - if (rank == ROOTP) { - cout << this->Vars(ii) << " " << this->InviscidFlux() << endl; - } - } else if (ii == 28 && readingBCs == 0) { - stagInletProps_[0] = stoi(tokens[1]); // tag - stagInletProps_[1] = stod(tokens[2]); // stag pressure - stagInletProps_[2] = stod(tokens[3]); // stag temp - stagInletProps_[3] = stod(tokens[4]); // dir-x - stagInletProps_[4] = stod(tokens[5]); // dir-y - stagInletProps_[5] = stod(tokens[6]); // dir-z - if (rank == ROOTP) { - cout << this->Vars(ii) << " " << this->StagInletTag() << " " - << this->StagInletP0() << " " << this->StagInletT0() - << " " << this->StagInletDx() << " " - << this->StagInletDy() << " " << this->StagInletDz() - << endl; - } - } else if (ii == 29 && readingBCs == 0) { - pressureOutlet_[0] = stoi(tokens[1]); // tag - pressureOutlet_[1] = stod(tokens[2]); // outlet pressure - if (rank == ROOTP) { - cout << this->Vars(ii) << " " << this->PressureOutletTag() - << " " << this->PressureOutletP() << endl; - } - } else if (ii == 30 && readingBCs == 0) { - decompMethod_ = tokens[1]; - if (rank == ROOTP) { - cout << this->Vars(ii) << " " << this->DecompMethod() << endl; - } - continue; - } else if (ii == 31 && readingBCs == 0) { - turbModel_ = tokens[1]; - if (rank == ROOTP) { - cout << this->Vars(ii) << " " << this->TurbulenceModel() - << endl; - } - continue; - } else if (ii == 32 && readingBCs == 0) { - farfieldTurbInten_ = stod(tokens[1]); // double (stod) - if (rank == ROOTP) { - cout << this->Vars(ii) << " " << this->FarfieldTurbIntensity() - << endl; - } - continue; - } else if (ii == 33 && readingBCs == 0) { - farfieldEddyViscRatio_ = stod(tokens[1]); // double (stod) - if (rank == ROOTP) { - cout << this->Vars(ii) << " " << this->FarfieldEddyViscRatio() - << endl; + if (rank == ROOTP) { + cout << key << " " << tokens[1] + << " kappa = " << this->Kappa() << endl; + } + if ((this->Kappa() < -1.0) || (this->Kappa() > 1.0)) { + cerr << "ERROR: Error in input::ReadInput(). Kappa value of " + << this->Kappa() + << " is not valid! Choose a value between -1.0 and 1.0." + << endl; + exit(EXIT_FAILURE); + } + } else if (key == "limiter:") { + limiter_ = tokens[1]; + if (rank == ROOTP) { + cout << key << " " << this->Limiter() << endl; + } + } else if (key == "outputFrequency:") { + outputFrequency_ = stoi(tokens[1]); + if (rank == ROOTP) { + cout << key << " " << this->OutputFrequency() << endl; + } + } else if (key == "equationSet:") { + equationSet_ = tokens[1]; + if (rank == ROOTP) { + cout << key << " " << this->EquationSet() << endl; + } + } else if (key == "temperatureRef:") { + tRef_ = stod(tokens[1]); // double variable (stod) + if (rank == ROOTP) { + cout << key << " " << this->TRef() << endl; + } + } else if (key == "matrixSolver:") { + matrixSolver_ = tokens[1]; + if (rank == ROOTP) { + cout << key << " " << this->MatrixSolver() << endl; + } + } else if (key == "matrixSweeps:") { + matrixSweeps_ = stoi(tokens[1]); + if (rank == ROOTP) { + cout << key << " " << this->MatrixSweeps() << endl; + } + } else if (key == "matrixRelaxation:") { + matrixRelaxation_ = + stod(tokens[1]); // double variable (stod) + if (rank == ROOTP) { + cout << key << " " << this->MatrixRelaxation() << endl; + } + } else if (key == "nonlinearIterations:") { + nonlinearIterations_ = stoi(tokens[1]); + if (rank == ROOTP) { + cout << key << " " << this->NonlinearIterations() << endl; + } + } else if (key == "cflMax:") { + cflMax_ = stod(tokens[1]); // double (stod) + if (rank == ROOTP) { + cout << key << " " << this->CFLMax() << endl; + } + } else if (key == "cflStep:") { + cflStep_ = stod(tokens[1]); // double (stod) + if (rank == ROOTP) { + cout << key << " " << this->CFLStep() << endl; + } + } else if (key == "cflStart:") { + cflStart_ = stod(tokens[1]); // double variable (stod) + if (rank == ROOTP) { + cout << key << " " << this->CFLStart() << endl; + } + } else if (key == "inviscidFluxJacobian:") { + invFluxJac_ = tokens[1]; + if (rank == ROOTP) { + cout << key << " " << this->InvFluxJac() << endl; + } + } else if (key == "dualTimeCFL:") { + dualTimeCFL_ = stod(tokens[1]); // double variable (stod) + if (rank == ROOTP) { + cout << key << " " << this->DualTimeCFL() << endl; + } + } else if (key == "inviscidFlux:") { + inviscidFlux_ = tokens[1]; + if (rank == ROOTP) { + cout << key << " " << this->InviscidFlux() << endl; + } + } else if (key == "stagnationInlet:") { + stagInletProps_[0] = stoi(tokens[1]); // tag + stagInletProps_[1] = stod(tokens[2]); // stag pressure + stagInletProps_[2] = stod(tokens[3]); // stag temp + stagInletProps_[3] = stod(tokens[4]); // dir-x + stagInletProps_[4] = stod(tokens[5]); // dir-y + stagInletProps_[5] = stod(tokens[6]); // dir-z + if (rank == ROOTP) { + cout << key << " " << this->StagInletTag() << " " + << this->StagInletP0() << " " << this->StagInletT0() + << " " << this->StagInletDx() << " " + << this->StagInletDy() << " " << this->StagInletDz() << endl; + } + } else if (key == "pressureOutlet:") { + pressureOutlet_[0] = stoi(tokens[1]); // tag + pressureOutlet_[1] = stod(tokens[2]); // outlet pressure + if (rank == ROOTP) { + cout << key << " " << this->PressureOutletTag() + << " " << this->PressureOutletP() << endl; + } + } else if (key == "decompositionMethod:") { + decompMethod_ = tokens[1]; + if (rank == ROOTP) { + cout << key << " " << this->DecompMethod() << endl; + } + } else if (key == "turbulenceModel:") { + turbModel_ = tokens[1]; + if (rank == ROOTP) { + cout << key << " " << this->TurbulenceModel() << endl; + } + } else if (key == "farfieldTurbulenceIntensity:") { + farfieldTurbInten_ = stod(tokens[1]); // double (stod) + if (rank == ROOTP) { + cout << key << " " << this->FarfieldTurbIntensity() << endl; + } + } else if (key == "farfieldEddyViscosityRatio:") { + farfieldEddyViscRatio_ = stod(tokens[1]); // double (stod) + if (rank == ROOTP) { + cout << key << " " << this->FarfieldEddyViscRatio() << endl; + } + } else if (key == "outputVariables:") { + // clear default variables from set + outputVariables_.clear(); + for (auto &vars : tokens) { + if (vars != key) { // don't add keyword + outputVariables_.insert(vars); } - continue; - - // reading BCs - // ------------------------------------------------------------- - } else if (ii == this->NumVars() - 1 || readingBCs > 0) { - // read in boundary conditions and assign to boundaryConditions - // class - if (readingBCs == 0) { // variable read must be number of blocks if - // first line of BCs - numBCBlks = stoi(tokens[1]); - tempBC.resize(numBCBlks); // resize vector holding BCs to correct - // number of blocks - readingBCs++; - lEnd++; - } else if (readingBCs == lEnd) { // variables must be number of i, - // j, k surfaces for each block - // set number of i, j, k surfaces and resize vectors - tempBC[blk].ResizeVecs(stoi(tokens[0]), - stoi(tokens[1]), - stoi(tokens[2])); - - // set total number of surfaces - numSurf = stoi(tokens[0]) + stoi(tokens[1]) + - stoi(tokens[2]); - - lEnd += (numSurf + - 1); // set new target for when block data is finished - readingBCs++; - - } else { // assign BC block variables - tempBC[blk].AssignFromInput(surfCounter, tokens); - - surfCounter++; - if (surfCounter == numSurf) { // at end of block data, increment - // block index, reset surface - // counter - blk++; - surfCounter = 0; + } + if (rank == ROOTP) { + cout << key << " "; + for (auto &vars : outputVariables_) { + if (vars != key) { // don't print keyword + cout << vars << " "; } - - readingBCs++; } + cout << endl; + } - // if block counter reaches number of blocks, BCs are finished (b/c - // counter starts at 0), so assign BCs and write them out - if (blk == numBCBlks) { - bc_ = tempBC; - if (rank == ROOTP) { - cout << this->Vars(this->NumVars() - 1) << " " - << this->NumBC() << endl << endl; - for (auto ll = 0; ll < this->NumBC(); ll++) { - cout << "Block: " << ll << endl; - cout << this->BC(ll) << endl; - } + // reading BCs + // ------------------------------------------------------------- + } else if (key == "boundaryConditions:" || readingBCs > 0) { + // read in boundary conditions and assign to boundaryConditions + // class + if (readingBCs == 0) { // variable read must be number of blocks if + // first line of BCs + numBCBlks = stoi(tokens[1]); + tempBC.resize(numBCBlks); // resize vector holding BCs to correct + // number of blocks + readingBCs++; + lEnd++; + } else if (readingBCs == lEnd) { // variables must be number of i, + // j, k surfaces for each block + // set number of i, j, k surfaces and resize vectors + tempBC[blk].ResizeVecs(stoi(tokens[0]), stoi(tokens[1]), + stoi(tokens[2])); + + // set total number of surfaces + numSurf = stoi(tokens[0]) + stoi(tokens[1]) + stoi(tokens[2]); + + // set new target for when block data is finished + lEnd += (numSurf + 1); + readingBCs++; + + } else { // assign BC block variables + tempBC[blk].AssignFromInput(surfCounter, tokens); + + surfCounter++; + if (surfCounter == numSurf) { // at end of block data, increment + // block index, reset surface + // counter + blk++; + surfCounter = 0; + } + + readingBCs++; + } + + // if block counter reaches number of blocks, BCs are finished (b/c + // counter starts at 0), so assign BCs and write them out + if (blk == numBCBlks) { + bc_ = tempBC; + if (rank == ROOTP) { + cout << "boundaryConditions: " << this->NumBC() << endl; + for (auto ll = 0; ll < this->NumBC(); ll++) { + cout << "Block: " << ll << endl; + cout << this->BC(ll) << endl; } } - - break; } } } - } else { // if there aren't 2 or more tokens just skip line - continue; } - } + } // if there aren't 2 or more tokens just skip line + // input file sanity checks this->CheckNonlinearIterations(); + this->CheckOutputVariables(); + this->CheckTurbulenceModel(); if (rank == ROOTP) { cout << endl; @@ -536,17 +503,10 @@ void input::ReadInput(const int &rank) { } } -// member function to calculate the cfl_ value for the step from the starting, +// member function to calculate the cfl value for the step from the starting, // ending, and step values -void input::CalcCFL(const int &i) { - if (i == 0) { // first time step - cfl_ = cflStart_; - } else if (cflStart_ + i * cflStep_ > - cflMax_) { // if calculated value is higher than max, set to max - cfl_ = cflMax_; - } else { - cfl_ = cflStart_ + i * cflStep_; - } +void input::CalcCFL(const int &ii) { + cfl_ = std::min(cflStart_ + ii * cflStep_, cflMax_); } // member function to determine number of turbulence equations @@ -606,7 +566,8 @@ bool input::IsTurbulent() const { // member function to determine if solution should use a block matrix bool input::IsBlockMatrix() const { - if (this->IsImplicit() && matrixSolver_ == "bdplur") { + if (this->IsImplicit() && (matrixSolver_ == "bdplur" || + matrixSolver_ == "blusgs")) { return true; } else { return false; @@ -633,7 +594,7 @@ unique_ptr input::AssignTurbulenceModel() const { } else { cerr << "ERROR: Error in input::AssignTurbulenceModel(). Turbulence model " << turbModel_ << " is not recognized!" << endl; - exit(0); + exit(EXIT_FAILURE); } return turb; } @@ -661,6 +622,46 @@ void input::CheckNonlinearIterations() { } } +// member function to check validity of the requested output variables +void input::CheckOutputVariables() { + for (auto var : outputVariables_) { + if (!this->IsTurbulent()) { // can't have turbulent varibles output + if (var == "tke" || var == "sdr" || var == "viscosityRatio" || + var.find("tkeGrad_") != string::npos || + var.find("sdrGrad_") != string::npos || var == "resid_tke" || + var == "resid_sdr") { + cerr << "WARNING: Variable " << var << + " is not available for laminar simulations." << endl; + outputVariables_.erase(var); + } + + if (!this->IsViscous()) { // can't have viscous variables output + if (var.find("velGrad_") != string::npos + || var.find("tempGrad_") != string::npos) { + cerr << "WARNING: Variable " << var << + " is not available for inviscid simulations." << endl; + outputVariables_.erase(var); + } + } + } + } +} + +// member function to check that turbulence model makes sense with equation set +void input::CheckTurbulenceModel() const { + if (equationSet_ == "rans" && turbModel_ == "none") { + cerr << "ERROR: If solving RANS equations, must specify turbulence model!" + << endl; + exit(EXIT_FAILURE); + } + if (equationSet_ != "rans" && turbModel_ != "none") { + cerr << "ERROR: Turbulence models are only valid for the RANS equation set!" + << endl; + exit(EXIT_FAILURE); + } +} + + // member function to calculate the coefficient used to scale the viscous // spectral radius in the time step calculation double input::ViscousCFLCoefficient() const { @@ -674,6 +675,8 @@ double input::ViscousCFLCoefficient() const { } bool input::MatrixRequiresInitialization() const { - // initialize matrix if using DPLUR, or if using LUSGS with more than one sweep - return (matrixSolver_ == "dplur" || matrixSweeps_ > 1) ? true : false; + // initialize matrix if using DPLUR / BDPLUR, or if using LUSGS / BLUSGS with + // more than one sweep + return (matrixSolver_ == "dplur" || matrixSolver_ == "bdplur" || + matrixSweeps_ > 1) ? true : false; } diff --git a/input.hpp b/input.hpp index e568f83..091c27a 100644 --- a/input.hpp +++ b/input.hpp @@ -20,6 +20,7 @@ #include // vector #include // string +#include // set #include // unique_ptr #include "vector3d.hpp" #include "boundaryConditions.hpp" @@ -27,6 +28,7 @@ using std::vector; using std::string; +using std::set; using std::unique_ptr; // forward class declaration @@ -38,9 +40,9 @@ class input { double dt_; // time step int iterations_; // number of iterations - // variable names that are regcognized by the input file - vector vars_; - // parser + // variable names that are regcognized by the input file parser + set vars_; + double pRef_; // reference pressure double rRef_; // reference density double lRef_; // reference length @@ -76,6 +78,8 @@ class input { double farfieldTurbInten_; // turbulence intensity at farfield double farfieldEddyViscRatio_; // eddy viscosity ratio at farfield + set outputVariables_; // variables to output + public: // constructor explicit input(const string &); @@ -121,6 +125,7 @@ class input { string Limiter() const {return limiter_;} int OutputFrequency() const {return outputFrequency_;} + set OutputVariables() const {return outputVariables_;} string EquationSet() const {return equationSet_;} @@ -158,9 +163,8 @@ class input { string DecompMethod() const {return decompMethod_;} string TurbulenceModel() const {return turbModel_;} - string Vars(const int &ind) const {return vars_[ind];} - int NumVars() const {return vars_.size();} + int NumVarsOutput() const {return outputVariables_.size();} int NumEquations() const; int NumFlowEquations() const {return NUMFLOWVARS;} int NumTurbEquations() const; @@ -180,6 +184,8 @@ class input { unique_ptr AssignTurbulenceModel() const; void CheckNonlinearIterations(); + void CheckOutputVariables(); + void CheckTurbulenceModel() const; double ViscousCFLCoefficient() const; diff --git a/inviscidFlux.cpp b/inviscidFlux.cpp index ed3606e..0de6edf 100644 --- a/inviscidFlux.cpp +++ b/inviscidFlux.cpp @@ -17,6 +17,7 @@ #include // sqrt #include #include +#include // max #include "inviscidFlux.hpp" #include "eos.hpp" #include "primVars.hpp" @@ -185,17 +186,19 @@ inviscidFlux RoeFlux(const primVars &left, const primVars &right, delta.Rho() - delta.P() / (aR * aR), (delta.P() + roe.Rho() * aR * normVelDiff) / (2.0 * aR * aR), roe.Rho(), - roe.Rho() * delta.Tke() + roe.Tke() * delta.Rho() - delta.P() * roe.Tke() / (aR * aR), - roe.Rho() * delta.Omega() + roe.Omega() * delta.Rho() - delta.P() * roe.Omega() / (aR * aR)}; + roe.Rho() * delta.Tke() + roe.Tke() * delta.Rho() - delta.P() * roe.Tke() + / (aR * aR), + roe.Rho() * delta.Omega() + roe.Omega() * delta.Rho() - + delta.P() * roe.Omega() / (aR * aR)}; // calculate absolute value of wave speeds (L) double waveSpeed[NUMVARS - 1] = { fabs(velRSum - aR), // left moving acoustic wave speed - fabs(velRSum), // entropy wave speed + fabs(velRSum), // entropy wave speed fabs(velRSum + aR), // right moving acoustic wave speed - fabs(velRSum), // shear wave speed - fabs(velRSum), // turbulent eqn 1 (k) wave speed - fabs(velRSum)}; // turbulent eqn 2 (omega) wave speed + fabs(velRSum), // shear wave speed + fabs(velRSum), // turbulent eqn 1 (k) wave speed + fabs(velRSum)}; // turbulent eqn 2 (omega) wave speed // calculate entropy fix (Harten) and adjust wave speeds if necessary // default setting for entropy fix to kick in @@ -209,11 +212,12 @@ inviscidFlux RoeFlux(const primVars &left, const primVars &right, waveSpeed[2] = 0.5 * (waveSpeed[2] * waveSpeed[2] / entropyFix + entropyFix); } - + // calculate right eigenvectors (T) // calculate eigenvector due to left acoustic wave const genArray lAcousticEigV(1.0, roe.U() - aR * areaNorm.X(), - roe.V() - aR * areaNorm.Y(), roe.W() - aR * areaNorm.Z(), + roe.V() - aR * areaNorm.Y(), + roe.W() - aR * areaNorm.Z(), hR - aR * velRSum, roe.Tke(), roe.Omega()); // calculate eigenvector due to entropy wave @@ -223,7 +227,8 @@ inviscidFlux RoeFlux(const primVars &left, const primVars &right, // calculate eigenvector due to right acoustic wave const genArray rAcousticEigV(1.0, roe.U() + aR * areaNorm.X(), - roe.V() + aR * areaNorm.Y(), roe.W() + aR * areaNorm.Z(), + roe.V() + aR * areaNorm.Y(), + roe.W() + aR * areaNorm.Z(), hR + aR * velRSum, roe.Tke(), roe.Omega()); // calculate eigenvector due to shear wave @@ -244,24 +249,18 @@ inviscidFlux RoeFlux(const primVars &left, const primVars &right, // calculate dissipation term ( eigenvector * wave speed * wave strength) genArray dissipation(0.0); for (auto ii = 0; ii < NUMVARS; ii++) { - dissipation[ii] = - waveSpeed[0] * waveStrength[0] * - lAcousticEigV[ii] // contribution from left acoustic wave - + - waveSpeed[1] * waveStrength[1] * - entropyEigV[ii] // contribution from entropy wave - + - waveSpeed[2] * waveStrength[2] * - rAcousticEigV[ii] // contribution from right acoustic wave - + - waveSpeed[3] * waveStrength[3] * - shearEigV[ii] // contribution from shear wave - + - waveSpeed[4] * waveStrength[4] * - tkeEigV[ii] // contribution from turbulent wave 1 - + - waveSpeed[5] * waveStrength[5] * - omgEigV[ii]; // contribution from turbulent wave 2 + // contribution from left acoustic wave + // contribution from entropy wave + // contribution from right acoustic wave + // contribution from shear wave + // contribution from turbulent wave 1 + // contribution from turbulent wave 2 + dissipation[ii] = waveSpeed[0] * waveStrength[0] * lAcousticEigV[ii] + + waveSpeed[1] * waveStrength[1] * entropyEigV[ii] + + waveSpeed[2] * waveStrength[2] * rAcousticEigV[ii] + + waveSpeed[3] * waveStrength[3] * shearEigV[ii] + + waveSpeed[4] * waveStrength[4] * tkeEigV[ii] + + waveSpeed[5] * waveStrength[5] * omgEigV[ii]; } // calculate left/right physical flux @@ -291,8 +290,8 @@ inviscidFlux RusanovFlux(const primVars &left, const primVars &right, const auto rightSpecRad = fabs(right.Velocity().DotProd(areaNorm)) + right.SoS(eqnState); const auto fac = positive ? -1.0 : 1.0; - const auto specRad = fac * max(leftSpecRad, rightSpecRad); - + const auto specRad = fac * std::max(leftSpecRad, rightSpecRad); + // calculate left/right physical flux inviscidFlux leftFlux(left, eqnState, areaNorm); inviscidFlux rightFlux(right, eqnState, areaNorm); @@ -349,7 +348,7 @@ genArray ConvectiveFluxUpdate(const primVars &state, const inviscidFlux newFlux(stateUpdate, eqnState, normArea); // calculate difference in flux - inviscidFlux dFlux = newFlux - oldFlux; + const auto dFlux = newFlux - oldFlux; return dFlux.ConvertToGenArray(); } diff --git a/macros.hpp b/macros.hpp index 4fbb0be..80f0c8e 100644 --- a/macros.hpp +++ b/macros.hpp @@ -24,7 +24,7 @@ #define ROOTP 0 #define DEFAULTWALLDIST 1.0e10 #define MAJORVERSION 0 -#define MINORVERSION 2 +#define MINORVERSION 3 #define PATCHNUMBER 0 #endif diff --git a/main.cpp b/main.cpp index fc1b948..abbc024 100644 --- a/main.cpp +++ b/main.cpp @@ -37,11 +37,11 @@ #include "genArray.hpp" #include "parallel.hpp" #include "turbulence.hpp" -#include "gradients.hpp" #include "resid.hpp" #include "multiArray3d.hpp" #include "kdtree.hpp" #include "fluxJacobian.hpp" +#include "utility.hpp" using std::cout; using std::cerr; @@ -135,7 +135,7 @@ int main(int argc, char *argv[]) { } else { cerr << "ERROR: Domain decomposition method " << inputVars.DecompMethod() << " is not recognized!" << endl; - exit(0); + exit(EXIT_FAILURE); } // Get interblock BCs @@ -143,20 +143,21 @@ int main(int argc, char *argv[]) { // Initialize the whole mesh with one state and assign ghost cells geometry stateBlocks.resize(mesh.size()); - for (auto ll = 0; ll < static_cast(mesh.size()); ll++) { + for (auto ll = 0U; ll < mesh.size(); ll++) { stateBlocks[ll] = procBlock(state, mesh[ll], decomp.ParentBlock(ll), numGhost, bcs[ll], ll, decomp.Rank(ll), - decomp.LocalPosition(ll) ); + decomp.LocalPosition(ll), inputVars, eos, + suth); stateBlocks[ll].AssignGhostCellsGeom(); } // Swap geometry for interblock BCs - for (auto ii = 0; ii < static_cast(connections.size()); ii++) { + for (auto ii = 0U; ii < connections.size(); ii++) { SwapGeomSlice(connections[ii], stateBlocks[connections[ii].BlockFirst()], stateBlocks[connections[ii].BlockSecond()]); } // Get ghost cell edge data - for (auto ll = 0; ll < static_cast(mesh.size()); ll++) { + for (auto ll = 0U; ll < mesh.size(); ll++) { stateBlocks[ll].AssignGhostCellsGeomEdge(); } @@ -169,10 +170,11 @@ int main(int argc, char *argv[]) { // Set MPI datatypes MPI_Datatype MPI_vec3d, MPI_cellData, MPI_procBlockInts, - MPI_interblock, MPI_DOUBLE_5INT, MPI_vec3dMag, MPI_uncoupledScalar; + MPI_interblock, MPI_DOUBLE_5INT, MPI_vec3dMag, MPI_uncoupledScalar, + MPI_tensorDouble; SetDataTypesMPI(MPI_vec3d, MPI_cellData, MPI_procBlockInts, MPI_interblock, MPI_DOUBLE_5INT, MPI_vec3dMag, - MPI_uncoupledScalar); + MPI_uncoupledScalar, MPI_tensorDouble); // Send number of procBlocks to all processors SendNumProcBlocks(decomp.NumBlocksOnAllProc(), numProcBlock); @@ -180,6 +182,11 @@ int main(int argc, char *argv[]) { // Send procBlocks to appropriate processor auto localStateBlocks = SendProcBlocks(stateBlocks, rank, numProcBlock, MPI_cellData, MPI_vec3d, MPI_vec3dMag); + // Update auxillary variables (temperature, viscosity, etc) + for (auto ll = 0U; ll < localStateBlocks.size(); ll++) { + localStateBlocks[ll].UpdateAuxillaryVariables(eos, suth, false); + localStateBlocks[ll].UpdateUnlimTurbEddyVisc(turb, false); + } // Send connections to all processors SendConnections(connections, MPI_interblock); @@ -237,7 +244,7 @@ int main(int argc, char *argv[]) { // Send/recv solutions - necessary to get wall distances GetProcBlocks(stateBlocks, localStateBlocks, rank, MPI_cellData, - MPI_uncoupledScalar); + MPI_uncoupledScalar, MPI_vec3d, MPI_tensorDouble); ofstream resFile; if (rank == ROOTP) { @@ -251,13 +258,15 @@ int main(int argc, char *argv[]) { // Write out initial results WriteFun(stateBlocks, eos, suth, 0, decomp, inputVars, turb); - WriteRes(inputVars.SimNameRoot(), 0, inputVars.OutputFrequency()); + WriteRes(inputVars, 0); } // ---------------------------------------------------------------------- // ----------------------- Start Main Loop ------------------------------ // ---------------------------------------------------------------------- for (auto nn = 0; nn < inputVars.Iterations(); nn++) { // loop over time + MPI_Barrier(MPI_COMM_WORLD); + // Calculate cfl number inputVars.CalcCFL(nn); @@ -272,31 +281,24 @@ int main(int argc, char *argv[]) { GetBoundaryConditions(localStateBlocks, inputVars, eos, suth, turb, connections, rank, MPI_cellData); - // Loop over number of blocks - for (auto bb = 0; bb < numProcBlock; bb++) { + + if (inputVars.IsImplicit()) { // Get solution at time M - N if implicit - if (inputVars.IsImplicit()) { - solDeltaMmN[bb] = localStateBlocks[bb].SolTimeMMinusN( - solTimeN[bb], eos, inputVars, mm); - if (nn == 0 && mm == 0) { - // At first iteration, resize array for old solution - solDeltaNm1[bb].ClearResize(localStateBlocks[bb].NumI(), - localStateBlocks[bb].NumJ(), - localStateBlocks[bb].NumK()); - mainDiagonal[bb].ClearResize(localStateBlocks[bb].NumI(), - localStateBlocks[bb].NumJ(), - localStateBlocks[bb].NumK()); - } + GetSolMMinusN(solDeltaMmN, localStateBlocks, solTimeN, eos, + inputVars, mm); + + if (nn == 0 && mm == 0) { + // At first iteration, resize array for old solution and jacobian + ResizeArrays(localStateBlocks, inputVars, solDeltaNm1, mainDiagonal); } + } - // Calculate residual (RHS) - localStateBlocks[bb].CalcResidual(suth, eos, inputVars, turb, - mainDiagonal[bb]); + // Calculate residual (RHS) + CalcResidual(localStateBlocks, mainDiagonal, suth, eos, inputVars, + turb, connections, rank, numGhost); - // Calculate the time step to use in the simulation - // (either user specified or derived from CFL) - localStateBlocks[bb].CalcBlockTimeStep(inputVars, aRef); - } + // Calculate time step + CalcTimeStep(localStateBlocks, inputVars, aRef); // Initialize residual variables genArray residL2(0.0); // l2 norm residuals @@ -340,16 +342,17 @@ int main(int argc, char *argv[]) { } } // loop for nonlinear iterations --------------------------------------- - if ((nn+1) % inputVars.OutputFrequency() == 0) { // write out function file + // write out function file + if ((nn + 1) % inputVars.OutputFrequency() == 0) { // Send/recv solutions GetProcBlocks(stateBlocks, localStateBlocks, rank, MPI_cellData, - MPI_uncoupledScalar); + MPI_uncoupledScalar, MPI_vec3d, MPI_tensorDouble); if (rank == ROOTP) { cout << "writing out function file at iteration " << nn << endl; // Write out function file WriteFun(stateBlocks, eos, suth, (nn+1), decomp, inputVars, turb); - WriteRes(inputVars.SimNameRoot(), (nn+1), inputVars.OutputFrequency()); + WriteRes(inputVars, (nn+1)); } } } // loop for time step ----------------------------------------------------- @@ -369,7 +372,7 @@ int main(int argc, char *argv[]) { // Free datatypes previously created FreeDataTypesMPI(MPI_vec3d, MPI_cellData, MPI_procBlockInts, MPI_interblock, MPI_DOUBLE_5INT, MPI_vec3dMag, - MPI_uncoupledScalar); + MPI_uncoupledScalar, MPI_tensorDouble); MPI_Finalize(); diff --git a/matrix.cpp b/matrix.cpp index c859601..a98384f 100644 --- a/matrix.cpp +++ b/matrix.cpp @@ -15,6 +15,7 @@ along with this program. If not, see . */ #include // exit() +#include // fabs #include // cout #include // swap #include "matrix.hpp" @@ -25,13 +26,12 @@ using std::endl; using std::cerr; using std::copy; using std::swap_ranges; -using std::fabs; // member function to swap rows of matrix void squareMatrix::SwapRows(const int &r1, const int &r2) { if (r1 != r2) { - for (auto ii = 0; ii < size_; ii++) { - std::swap(data_[this->GetLoc(ii, r1)], data_[this->GetLoc(ii, r2)]); + for (auto cc = 0; cc < size_; cc++) { + std::swap((*this)(r1, cc), (*this)(r2, cc)); } } } @@ -62,7 +62,7 @@ void squareMatrix::Inverse() { if ((*this)(r, cPivot) == 0.0) { cerr << "ERROR: Singular matrix in Gauss-Jordan elimination! Matrix (mid " "inversion) is" << endl << *this << endl; - exit(1); + exit(EXIT_FAILURE); } auto normFactor = 1.0 / (*this)(r, cPivot); this->RowMultiply(r, cPivot, normFactor); // only multiply entries from @@ -106,7 +106,7 @@ int squareMatrix::FindMaxInCol(const int &c, const int &start, const int &end) const { auto maxVal = 0.0; auto maxRow = 0; - for (auto ii = start; ii < end + 1; ii++) { + for (auto ii = start; ii <= end; ii++) { if (fabs((*this)(ii, c)) > maxVal) { maxVal = fabs((*this)(ii, c)); maxRow = ii; @@ -117,21 +117,14 @@ int squareMatrix::FindMaxInCol(const int &c, const int &start, // operator overload for multiplication +// using cache efficient implimentation squareMatrix squareMatrix::MatMult(const squareMatrix &s2) const { - // check to see that matrix dimensions are the same - if (size_ != s2.size_) { - cerr << "ERROR: Cannot multiply matrices, dimensions do not agree." << endl; - } - - auto s1 = *this; - + squareMatrix s1(s2.Size()); for (auto cc = 0; cc < s2.Size(); cc++) { for (auto rr = 0; rr < s2.Size(); rr++) { - auto newVal = 0.0; for (auto ii = 0; ii < s2.Size(); ii++) { - newVal += (*this)(rr, ii) * s2(ii, cc); + s1(rr, ii) += (*this)(rr, cc) * s2(cc, ii); } - s1(rr, cc) = newVal; } } return s1; @@ -141,11 +134,11 @@ squareMatrix squareMatrix::MatMult(const squareMatrix &s2) const { ostream &operator<<(ostream &os, const squareMatrix &m) { for (auto rr = 0; rr < m.Size(); rr++) { for (auto cc = 0; cc < m.Size(); cc++) { - cout << m(rr, cc); + os << m(rr, cc); if (cc != (m.Size() - 1)) { - cout << ", "; + os << ", "; } else { - cout << endl; + os << endl; } } } @@ -176,11 +169,33 @@ void squareMatrix::Identity() { genArray squareMatrix::ArrayMult(const genArray &vec, const int pos) const { // vec -- vector to multiply with - genArray product(0.0); + auto product = vec; + + // zero out portion of genArray that will be written over + if (pos == 0) { + for (auto ii = 0; ii < NUMFLOWVARS; ii++) { + product[ii] = 0.0; + } + } else { + for (auto ii = pos; ii < NUMVARS; ii++) { + product[ii] = 0.0; + } + } + for (auto rr = 0; rr < size_; rr++) { for (auto cc = 0; cc < size_; cc++) { - product[rr] += (*this)(rr, cc) * vec[pos + cc]; + product[pos + rr] += (*this)(rr, cc) * vec[pos + cc]; } } return product; } + +// member function to find maximum absolute value on diagonal +// this can be used to find the spectral radius of a diagoanl matrix +double squareMatrix::MaxAbsValOnDiagonal() const { + auto maxVal = 0.0; + for (auto ii = 0; ii < size_; ii++) { + maxVal = std::max(fabs((*this)(ii, ii)), maxVal); + } + return maxVal; +} diff --git a/matrix.hpp b/matrix.hpp index 3b8fcf6..ab29988 100644 --- a/matrix.hpp +++ b/matrix.hpp @@ -35,7 +35,7 @@ class squareMatrix { // private member functions int GetLoc(const int &r, const int &c) const { - return c + r * size_; + return r * size_ + c; } public: @@ -62,7 +62,8 @@ class squareMatrix { void Identity(); squareMatrix MatMult(const squareMatrix &) const; genArray ArrayMult(const genArray &, const int = 0) const; - + double MaxAbsValOnDiagonal() const; + // operator overloads double & operator()(const int &r, const int &c) { return data_[this->GetLoc(r, c)]; @@ -108,7 +109,7 @@ ostream &operator<<(ostream &os, const squareMatrix &); // operator overload for addition squareMatrix & squareMatrix::operator+=(const squareMatrix &mat) { - for (auto ii = 0; ii < static_cast(mat.data_.size()); ii++) { + for (auto ii = 0U; ii < mat.data_.size(); ii++) { data_[ii] += mat.data_[ii]; } return *this; @@ -116,7 +117,7 @@ squareMatrix & squareMatrix::operator+=(const squareMatrix &mat) { // operator overload for subtraction squareMatrix & squareMatrix::operator-=(const squareMatrix &mat) { - for (auto ii = 0; ii < static_cast(mat.data_.size()); ii++) { + for (auto ii = 0U; ii < mat.data_.size(); ii++) { data_[ii] -= mat.data_[ii]; } return *this; @@ -124,7 +125,7 @@ squareMatrix & squareMatrix::operator-=(const squareMatrix &mat) { // operator overload for elementwise multiplication squareMatrix & squareMatrix::operator*=(const squareMatrix &mat) { - for (auto ii = 0; ii < static_cast(mat.data_.size()); ii++) { + for (auto ii = 0U; ii < mat.data_.size(); ii++) { data_[ii] *= mat.data_[ii]; } return *this; @@ -132,7 +133,7 @@ squareMatrix & squareMatrix::operator*=(const squareMatrix &mat) { // operator overload for elementwise multiplication squareMatrix & squareMatrix::operator/=(const squareMatrix &mat) { - for (auto ii = 0; ii < static_cast(mat.data_.size()); ii++) { + for (auto ii = 0U; ii < mat.data_.size(); ii++) { data_[ii] /= mat.data_[ii]; } return *this; diff --git a/multiArray3d.hpp b/multiArray3d.hpp index a74cce0..768837b 100644 --- a/multiArray3d.hpp +++ b/multiArray3d.hpp @@ -51,10 +51,10 @@ class multiArray3d { public: // constructor multiArray3d(const int &ii, const int &jj, const int &kk, const T &init) : - data_(vector(ii * jj * kk, init)), + data_(ii * jj * kk, init), numI_(ii), numJ_(jj), numK_(kk) {} multiArray3d(const int &ii, const int &jj, const int &kk) : - data_(vector(ii * jj * kk)), + data_(ii * jj * kk), numI_(ii), numJ_(jj), numK_(kk) {} multiArray3d() : multiArray3d(1, 1, 1) {} @@ -79,17 +79,19 @@ class multiArray3d { void PutSlice(const multiArray3d &, const interblock &, const int &, const int &); void SwapSliceMPI(const interblock&, const int&, const MPI_Datatype&, - const int&); + const int&, const int = 1); void SwapSlice(const interblock&, multiArray3d&, const int&, const int&); void Zero(const T&); + void Zero(); void GrowI(); void GrowJ(); void GrowK(); - void PackSwapUnpackMPI(const interblock &, const MPI_Datatype &, const int &); + void PackSwapUnpackMPI(const interblock &, const MPI_Datatype &, const int &, + const int = 1); T GetElem(const int &ii, const int &jj, const int &kk) const; @@ -139,32 +141,60 @@ class multiArray3d { // arithmetic with a type that is not *this or the type *this is holding // used for example to multiply with a double if *this is a // multiArray3d> + template - inline multiArray3d & operator+=(const TT &); + multiArray3d & operator+=(const TT &scalar) { + for (auto &val : data_) { + val += scalar; + } + return *this; + } + template - inline multiArray3d & operator-=(const TT &); + multiArray3d & operator-=(const TT &scalar) { + for (auto &val : data_) { + val -= scalar; + } + return *this; + } + template - inline multiArray3d & operator*=(const TT &); + multiArray3d & operator*=(const TT &scalar) { + for (auto &val : data_) { + val *= scalar; + } + return *this; + } + template - inline multiArray3d & operator/=(const TT &); + multiArray3d & operator/=(const TT &scalar) { + for (auto &val : data_) { + val /= scalar; + } + return *this; + } template - inline multiArray3d operator+(const TT &s) const { + multiArray3d operator+( + std::enable_if_t::value, TT> const &s) const { auto lhs = *this; return lhs += s; } template - inline multiArray3d operator-(const TT &s) const { + multiArray3d operator-( + std::enable_if_t::value, TT> const &s) const { auto lhs = *this; return lhs -= s; } template - inline multiArray3d operator*(const TT &s) const { + multiArray3d operator*( + std::enable_if_t::value, TT> const &s) const { auto lhs = *this; return lhs *= s; } template - inline multiArray3d operator/(const TT &s) const { + multiArray3d operator/( + std::enable_if_t::value, TT> const &s) const { auto lhs = *this; return lhs /= s; } @@ -192,7 +222,7 @@ T multiArray3d::GetElem(const int &ii, const int &jj, const int &kk) const { cerr << "Tried to access " << ii << ", " << jj << ", " << kk << endl; cerr << "Maximum locations are " << numI_ - 1 << ", " << numJ_ - 1 << ", " << numK_ - 1 << endl; - exit(0); + exit(1); } } @@ -325,42 +355,6 @@ inline const multiArray3d operator/(const T &lhs, multiArray3d rhs) { // ---------------------------------------------------------------- // operator overloads type that is not *this, or the type *this is holding -// operator overload for addition -template template -multiArray3d & multiArray3d::operator+=(const TT &scalar) { - for (auto &val : data_) { - val += scalar; - } - return *this; -} - -// operator overload for subtraction with a scalar -template template -multiArray3d & multiArray3d::operator-=(const TT &scalar) { - for (auto &val : data_) { - val -= scalar; - } - return *this; -} - -// operator overload for elementwise multiplication -template template -multiArray3d & multiArray3d::operator*=(const TT &scalar) { - for (auto &val : data_) { - val *= scalar; - } - return *this; -} - -// operator overload for elementwise division -template template -multiArray3d & multiArray3d::operator/=(const TT &scalar) { - for (auto &val : data_) { - val /= scalar; - } - return *this; -} - template inline const multiArray3d operator+(const TT &lhs, multiArray3d rhs) { return rhs += lhs; @@ -409,7 +403,7 @@ multiArray3d multiArray3d::Slice(const int &is, const int &ie, << "boundaries " << is << ", " << ie << ", " << js << ", " << je << ", " << ks << ", " << ke << " from array with dimensions " << numI_ << ", " << numJ_ << ", " << numK_ << endl; - exit(0); + exit(1); } multiArray3d array(ie - is + 1, je - js + 1, ke - ks + 1); @@ -448,7 +442,7 @@ void multiArray3d::Insert(const int &is, const int &ie, const int &js, ", " << array.numK_ << endl; cerr << "Size of location is " << ie - is + 1 << ", " << je - js + 1 << ", " << ke - ks + 1 << endl; - exit(0); + exit(1); } // s is for index of sliced array, p is for index of parent array @@ -510,7 +504,7 @@ void multiArray3d::SameSizeResize(const int &ii, const int&jj, cerr << "ERROR: Error in multiArray3d::SameSizeResize. Attempting to " << "resize array of " << this->Size() << " cells to " << ii * jj * kk << " cells." << endl; - exit(0); + exit(1); } numI_ = ii; numJ_ = jj; @@ -525,6 +519,15 @@ void multiArray3d::Zero(const T &zero) { } } +// member function to "zero out" the container with an available "Zero" function +template +void multiArray3d::Zero() { + for (auto &val : data_) { + val.Zero(); + } +} + + // operation overload for << - allows use of cout, cerr, etc. template ostream &operator<<(ostream &os, const multiArray3d &array) { @@ -562,7 +565,7 @@ void multiArray3d::PutSlice(const multiArray3d &array, << inter.Dir2EndFirst() - inter.Dir2StartFirst() << ", " << d3 << endl; cerr << "Direction I, J, K of multiArray3d to insert: " << array.NumI() << ", " << array.NumJ() << ", " << array.NumK() << endl; - exit(0); + exit(1); } // adjust insertion indices if patch borders another interblock on the same @@ -593,17 +596,18 @@ void multiArray3d::PutSlice(const multiArray3d &array, * interblock partner, and then unpack it into an array.*/ template void multiArray3d::PackSwapUnpackMPI(const interblock &inter, - const MPI_Datatype &MPI_cellData, - const int &rank) { + const MPI_Datatype &MPI_arrData, + const int &rank, const int tag) { // inter -- interblock boundary for the swap - // MPI_cellData -- MPI datatype to pass data type in array + // MPI_arrData -- MPI datatype to pass data type in array // rank -- processor rank + // tag -- id to send data with (default 1) // swap with mpi_send_recv_replace // pack data into buffer, but first get size auto bufSize = 0; auto tempSize = 0; - MPI_Pack_size(this->Size(), MPI_cellData, MPI_COMM_WORLD, + MPI_Pack_size(this->Size(), MPI_arrData, MPI_COMM_WORLD, &tempSize); // add size for states bufSize += tempSize; // add size for 3 ints for multiArray3d dims @@ -624,16 +628,16 @@ void multiArray3d::PackSwapUnpackMPI(const interblock &inter, MPI_COMM_WORLD); MPI_Pack(&numK, 1, MPI_INT, buffer, bufSize, &position, MPI_COMM_WORLD); - MPI_Pack(&data_[0], this->Size(), MPI_cellData, buffer, + MPI_Pack(&data_[0], this->Size(), MPI_arrData, buffer, bufSize, &position, MPI_COMM_WORLD); MPI_Status status; if (rank == inter.RankFirst()) { // send/recv with second entry in interblock - MPI_Sendrecv_replace(buffer, bufSize, MPI_PACKED, inter.RankSecond(), 1, - inter.RankSecond(), 1, MPI_COMM_WORLD, &status); + MPI_Sendrecv_replace(buffer, bufSize, MPI_PACKED, inter.RankSecond(), tag, + inter.RankSecond(), tag, MPI_COMM_WORLD, &status); } else { // send/recv with first entry in interblock - MPI_Sendrecv_replace(buffer, bufSize, MPI_PACKED, inter.RankFirst(), 1, - inter.RankFirst(), 1, MPI_COMM_WORLD, &status); + MPI_Sendrecv_replace(buffer, bufSize, MPI_PACKED, inter.RankFirst(), tag, + inter.RankFirst(), tag, MPI_COMM_WORLD, &status); } // put slice back into multiArray3d @@ -648,7 +652,7 @@ void multiArray3d::PackSwapUnpackMPI(const interblock &inter, this->SameSizeResize(numI, numJ, numK); MPI_Unpack(buffer, bufSize, &position, &data_[0], - this->Size(), MPI_cellData, MPI_COMM_WORLD); + this->Size(), MPI_arrData, MPI_COMM_WORLD); delete[] buffer; } @@ -659,12 +663,13 @@ processors. */ template void multiArray3d::SwapSliceMPI(const interblock &inter, const int &rank, - const MPI_Datatype &MPI_cellData, - const int &numGhosts) { + const MPI_Datatype &MPI_arrData, + const int &numGhosts, const int tag) { // inter -- interblock boundary information // rank -- processor rank - // MPI_cellData -- MPI datatype for passing primVars, genArray + // MPI_arrData -- MPI datatype for passing data in *this // numGhosts -- number of ghost cells + // tag -- id for MPI swap (default 1) // Get indices for slice coming from block to swap auto is = 0; @@ -682,14 +687,14 @@ void multiArray3d::SwapSliceMPI(const interblock &inter, const int &rank, } else { cerr << "ERROR: Error in procBlock::SwapSliceMPI(). Processor rank does " "not match either of interblock ranks!" << endl; - exit(0); + exit(1); } // get local state slice to swap auto slice = this->Slice(is, ie, js, je, ks, ke); // swap state slices with partner block - slice.PackSwapUnpackMPI(inter, MPI_cellData, rank); + slice.PackSwapUnpackMPI(inter, MPI_arrData, rank, tag); // change interblocks to work with slice and ghosts auto interAdj = inter; diff --git a/output.cpp b/output.cpp index ed5e1ef..4c67c5e 100644 --- a/output.cpp +++ b/output.cpp @@ -36,8 +36,6 @@ #include "resid.hpp" // resid #include "genArray.hpp" // genArray -#define VAROUT 15 - using std::cout; using std::endl; using std::cerr; @@ -70,7 +68,7 @@ void WriteCellCenter(const string &gridName, const vector &vars, if (outFile.fail()) { cerr << "ERROR: Grid file " << writeName << " did not open correctly!!!" << endl; - exit(0); + exit(EXIT_FAILURE); } // write number of blocks to file @@ -141,7 +139,7 @@ void WriteFun(const vector &vars, const idealGas &eqnState, if (outFile.fail()) { cerr << "ERROR: Function file " << writeName << " did not open correctly!!!" << endl; - exit(0); + exit(EXIT_FAILURE); } // write number of blocks to file @@ -149,7 +147,7 @@ void WriteFun(const vector &vars, const idealGas &eqnState, outFile.write(reinterpret_cast(&numBlks), sizeof(numBlks)); // write i, j, k, recombVars dimension for each block - auto numVars = VAROUT; // number of variables to write out + auto numVars = inp.NumVarsOutput(); // number of variables to write out // loop over all blocks and write out imax, jmax, kmax, numVars for (auto ll = 0; ll < numBlks; ll++) { @@ -169,10 +167,10 @@ void WriteFun(const vector &vars, const idealGas &eqnState, recombVars[ll].NumK()); // loop over the number of variables to write out - for (auto vv = 0; vv < numVars; vv++) { + for (auto &var : inp.OutputVariables()) { // store nondimensional variable in dumArr for a given block in order. // i.e. var1 var2 var3 etc - if (vv == 0) { // density + if (var == "density") { for (auto kp = 0, kg = recombVars[ll].NumGhosts(); kp < recombVars[ll].NumK(); kg++, kp++) { for (auto jp = 0, jg = recombVars[ll].NumGhosts(); @@ -184,7 +182,7 @@ void WriteFun(const vector &vars, const idealGas &eqnState, } } } - } else if (vv == 1) { // vel-x + } else if (var == "vel_x") { for (auto kp = 0, kg = recombVars[ll].NumGhosts(); kp < recombVars[ll].NumK(); kg++, kp++) { for (auto jp = 0, jg = recombVars[ll].NumGhosts(); @@ -196,7 +194,7 @@ void WriteFun(const vector &vars, const idealGas &eqnState, } } } - } else if (vv == 2) { // vel-y + } else if (var == "vel_y") { for (auto kp = 0, kg = recombVars[ll].NumGhosts(); kp < recombVars[ll].NumK(); kg++, kp++) { for (auto jp = 0, jg = recombVars[ll].NumGhosts(); @@ -208,7 +206,7 @@ void WriteFun(const vector &vars, const idealGas &eqnState, } } } - } else if (vv == 3) { // vel-z + } else if (var == "vel_z") { for (auto kp = 0, kg = recombVars[ll].NumGhosts(); kp < recombVars[ll].NumK(); kg++, kp++) { for (auto jp = 0, jg = recombVars[ll].NumGhosts(); @@ -220,7 +218,7 @@ void WriteFun(const vector &vars, const idealGas &eqnState, } } } - } else if (vv == 4) { // pressure + } else if (var == "pressure") { for (auto kp = 0, kg = recombVars[ll].NumGhosts(); kp < recombVars[ll].NumK(); kg++, kp++) { for (auto jp = 0, jg = recombVars[ll].NumGhosts(); @@ -232,7 +230,7 @@ void WriteFun(const vector &vars, const idealGas &eqnState, } } } - } else if (vv == 5) { // mach + } else if (var == "mach") { for (auto kp = 0, kg = recombVars[ll].NumGhosts(); kp < recombVars[ll].NumK(); kg++, kp++) { for (auto jp = 0, jg = recombVars[ll].NumGhosts(); @@ -247,7 +245,7 @@ void WriteFun(const vector &vars, const idealGas &eqnState, } } } - } else if (vv == 6) { // speed of sound + } else if (var == "sos") { for (auto kp = 0, kg = recombVars[ll].NumGhosts(); kp < recombVars[ll].NumK(); kg++, kp++) { for (auto jp = 0, jg = recombVars[ll].NumGhosts(); @@ -260,27 +258,26 @@ void WriteFun(const vector &vars, const idealGas &eqnState, } } } - } else if (vv == 7) { // time step - no ghost cells - for (auto kk = 0; kk < recombVars[ll].NumK(); kk++) { + } else if (var == "dt") { // time step - no ghost cells + for (auto kk = 0; kk < recombVars[ll].NumK(); kk++) { for (auto jj = 0; jj < recombVars[ll].NumJ(); jj++) { for (auto ii = 0; ii < recombVars[ll].NumI(); ii++) { dumArr(ii, jj, kk) = recombVars[ll].Dt(ii, jj, kk); } } } - } else if (vv == 8) { // temperature + } else if (var == "temperature") { for (auto kp = 0, kg = recombVars[ll].NumGhosts(); kp < recombVars[ll].NumK(); kg++, kp++) { for (auto jp = 0, jg = recombVars[ll].NumGhosts(); jp < recombVars[ll].NumJ(); jg++, jp++) { for (auto ip = 0, ig = recombVars[ll].NumGhosts(); ip < recombVars[ll].NumI(); ig++, ip++) { - dumArr(ip, jp, kp) = - recombVars[ll].State(ig, jg, kg).Temperature(eqnState); + dumArr(ip, jp, kp) = recombVars[ll].Temperature(ig, jg, kg); } } } - } else if (vv == 9) { // processor rank + } else if (var == "rank") { for (auto kk = 0; kk < recombVars[ll].NumK(); kk++) { for (auto jj = 0; jj < recombVars[ll].NumJ(); jj++) { for (auto ii = 0; ii < recombVars[ll].NumI(); ii++) { @@ -289,7 +286,7 @@ void WriteFun(const vector &vars, const idealGas &eqnState, } } } - } else if (vv == 10) { // global position + } else if (var == "globalPosition") { for (auto kk = 0; kk < recombVars[ll].NumK(); kk++) { for (auto jj = 0; jj < recombVars[ll].NumJ(); jj++) { for (auto ii = 0; ii < recombVars[ll].NumI(); ii++) { @@ -299,21 +296,21 @@ void WriteFun(const vector &vars, const idealGas &eqnState, } } } - } else if (vv == 11) { // viscosity ratio + } else if (var == "viscosityRatio") { for (auto kp = 0, kg = recombVars[ll].NumGhosts(); kp < recombVars[ll].NumK(); kg++, kp++) { for (auto jp = 0, jg = recombVars[ll].NumGhosts(); jp < recombVars[ll].NumJ(); jg++, jp++) { for (auto ip = 0, ig = recombVars[ll].NumGhosts(); ip < recombVars[ll].NumI(); ig++, ip++) { - dumArr(ip, jp, kp) = - turb->EddyViscNoLim(recombVars[ll].State(ig, jg, kg)) / - suth.Viscosity(recombVars[ll].State(ig, jg, kg). - Temperature(eqnState)); + dumArr(ip, jp, kp) = recombVars[ll].IsTurbulent() ? + recombVars[ll].EddyViscosity(ig, jg, kg) / + recombVars[ll].Viscosity(ig, jg, kg) + : 0.0; } } } - } else if (vv == 12) { // tke + } else if (var == "tke") { for (auto kp = 0, kg = recombVars[ll].NumGhosts(); kp < recombVars[ll].NumK(); kg++, kp++) { for (auto jp = 0, jg = recombVars[ll].NumGhosts(); @@ -325,7 +322,7 @@ void WriteFun(const vector &vars, const idealGas &eqnState, } } } - } else if (vv == 13) { // omega + } else if (var == "sdr") { // omega (specific dissipation rate) for (auto kp = 0, kg = recombVars[ll].NumGhosts(); kp < recombVars[ll].NumK(); kg++, kp++) { for (auto jp = 0, jg = recombVars[ll].NumGhosts(); @@ -337,7 +334,7 @@ void WriteFun(const vector &vars, const idealGas &eqnState, } } } - } else if (vv == 14) { // wall distance + } else if (var == "wallDistance") { for (auto kp = 0, kg = recombVars[ll].NumGhosts(); kp < recombVars[ll].NumK(); kg++, kp++) { for (auto jp = 0, jg = recombVars[ll].NumGhosts(); @@ -349,10 +346,210 @@ void WriteFun(const vector &vars, const idealGas &eqnState, } } } + } else if (var == "velGrad_ux") { + for (auto kk = 0; kk < recombVars[ll].NumK(); kk++) { + for (auto jj = 0; jj < recombVars[ll].NumJ(); jj++) { + for (auto ii = 0; ii < recombVars[ll].NumI(); ii++) { + dumArr(ii, jj, kk) = recombVars[ll].VelGrad(ii, jj, kk).XX(); + } + } + } + } else if (var == "velGrad_vx") { + for (auto kk = 0; kk < recombVars[ll].NumK(); kk++) { + for (auto jj = 0; jj < recombVars[ll].NumJ(); jj++) { + for (auto ii = 0; ii < recombVars[ll].NumI(); ii++) { + dumArr(ii, jj, kk) = recombVars[ll].VelGrad(ii, jj, kk).XY(); + } + } + } + } else if (var == "velGrad_wx") { + for (auto kk = 0; kk < recombVars[ll].NumK(); kk++) { + for (auto jj = 0; jj < recombVars[ll].NumJ(); jj++) { + for (auto ii = 0; ii < recombVars[ll].NumI(); ii++) { + dumArr(ii, jj, kk) = recombVars[ll].VelGrad(ii, jj, kk).XZ(); + } + } + } + } else if (var == "velGrad_uy") { + for (auto kk = 0; kk < recombVars[ll].NumK(); kk++) { + for (auto jj = 0; jj < recombVars[ll].NumJ(); jj++) { + for (auto ii = 0; ii < recombVars[ll].NumI(); ii++) { + dumArr(ii, jj, kk) = recombVars[ll].VelGrad(ii, jj, kk).YX(); + } + } + } + } else if (var == "velGrad_vy") { + for (auto kk = 0; kk < recombVars[ll].NumK(); kk++) { + for (auto jj = 0; jj < recombVars[ll].NumJ(); jj++) { + for (auto ii = 0; ii < recombVars[ll].NumI(); ii++) { + dumArr(ii, jj, kk) = recombVars[ll].VelGrad(ii, jj, kk).YY(); + } + } + } + } else if (var == "velGrad_wy") { + for (auto kk = 0; kk < recombVars[ll].NumK(); kk++) { + for (auto jj = 0; jj < recombVars[ll].NumJ(); jj++) { + for (auto ii = 0; ii < recombVars[ll].NumI(); ii++) { + dumArr(ii, jj, kk) = recombVars[ll].VelGrad(ii, jj, kk).YZ(); + } + } + } + } else if (var == "velGrad_uz") { + for (auto kk = 0; kk < recombVars[ll].NumK(); kk++) { + for (auto jj = 0; jj < recombVars[ll].NumJ(); jj++) { + for (auto ii = 0; ii < recombVars[ll].NumI(); ii++) { + dumArr(ii, jj, kk) = recombVars[ll].VelGrad(ii, jj, kk).ZX(); + } + } + } + } else if (var == "velGrad_vz") { + for (auto kk = 0; kk < recombVars[ll].NumK(); kk++) { + for (auto jj = 0; jj < recombVars[ll].NumJ(); jj++) { + for (auto ii = 0; ii < recombVars[ll].NumI(); ii++) { + dumArr(ii, jj, kk) = recombVars[ll].VelGrad(ii, jj, kk).ZY(); + } + } + } + } else if (var == "velGrad_wz") { + for (auto kk = 0; kk < recombVars[ll].NumK(); kk++) { + for (auto jj = 0; jj < recombVars[ll].NumJ(); jj++) { + for (auto ii = 0; ii < recombVars[ll].NumI(); ii++) { + dumArr(ii, jj, kk) = recombVars[ll].VelGrad(ii, jj, kk).ZZ(); + } + } + } + } else if (var == "tempGrad_x") { + for (auto kk = 0; kk < recombVars[ll].NumK(); kk++) { + for (auto jj = 0; jj < recombVars[ll].NumJ(); jj++) { + for (auto ii = 0; ii < recombVars[ll].NumI(); ii++) { + dumArr(ii, jj, kk) = recombVars[ll].TempGrad(ii, jj, kk).X(); + } + } + } + } else if (var == "tempGrad_y") { + for (auto kk = 0; kk < recombVars[ll].NumK(); kk++) { + for (auto jj = 0; jj < recombVars[ll].NumJ(); jj++) { + for (auto ii = 0; ii < recombVars[ll].NumI(); ii++) { + dumArr(ii, jj, kk) = recombVars[ll].TempGrad(ii, jj, kk).Y(); + } + } + } + } else if (var == "tempGrad_z") { + for (auto kk = 0; kk < recombVars[ll].NumK(); kk++) { + for (auto jj = 0; jj < recombVars[ll].NumJ(); jj++) { + for (auto ii = 0; ii < recombVars[ll].NumI(); ii++) { + dumArr(ii, jj, kk) = recombVars[ll].TempGrad(ii, jj, kk).Z(); + } + } + } + } else if (var == "tkeGrad_x") { + for (auto kk = 0; kk < recombVars[ll].NumK(); kk++) { + for (auto jj = 0; jj < recombVars[ll].NumJ(); jj++) { + for (auto ii = 0; ii < recombVars[ll].NumI(); ii++) { + dumArr(ii, jj, kk) = recombVars[ll].TkeGrad(ii, jj, kk).X(); + } + } + } + } else if (var == "tkeGrad_y") { + for (auto kk = 0; kk < recombVars[ll].NumK(); kk++) { + for (auto jj = 0; jj < recombVars[ll].NumJ(); jj++) { + for (auto ii = 0; ii < recombVars[ll].NumI(); ii++) { + dumArr(ii, jj, kk) = recombVars[ll].TkeGrad(ii, jj, kk).Y(); + } + } + } + } else if (var == "tkeGrad_z") { + for (auto kk = 0; kk < recombVars[ll].NumK(); kk++) { + for (auto jj = 0; jj < recombVars[ll].NumJ(); jj++) { + for (auto ii = 0; ii < recombVars[ll].NumI(); ii++) { + dumArr(ii, jj, kk) = recombVars[ll].TkeGrad(ii, jj, kk).Z(); + } + } + } + } else if (var == "sdrGrad_x") { + for (auto kk = 0; kk < recombVars[ll].NumK(); kk++) { + for (auto jj = 0; jj < recombVars[ll].NumJ(); jj++) { + for (auto ii = 0; ii < recombVars[ll].NumI(); ii++) { + dumArr(ii, jj, kk) = recombVars[ll].OmegaGrad(ii, jj, kk).X(); + } + } + } + } else if (var == "sdrGrad_y") { + for (auto kk = 0; kk < recombVars[ll].NumK(); kk++) { + for (auto jj = 0; jj < recombVars[ll].NumJ(); jj++) { + for (auto ii = 0; ii < recombVars[ll].NumI(); ii++) { + dumArr(ii, jj, kk) = recombVars[ll].OmegaGrad(ii, jj, kk).Y(); + } + } + } + } else if (var == "sdrGrad_z") { + for (auto kk = 0; kk < recombVars[ll].NumK(); kk++) { + for (auto jj = 0; jj < recombVars[ll].NumJ(); jj++) { + for (auto ii = 0; ii < recombVars[ll].NumI(); ii++) { + dumArr(ii, jj, kk) = recombVars[ll].OmegaGrad(ii, jj, kk).Z(); + } + } + } + } else if (var == "resid_mass") { + for (auto kk = 0; kk < recombVars[ll].NumK(); kk++) { + for (auto jj = 0; jj < recombVars[ll].NumJ(); jj++) { + for (auto ii = 0; ii < recombVars[ll].NumI(); ii++) { + dumArr(ii, jj, kk) = recombVars[ll].Residual(ii, jj, kk, 0); + } + } + } + } else if (var == "resid_mom_x") { + for (auto kk = 0; kk < recombVars[ll].NumK(); kk++) { + for (auto jj = 0; jj < recombVars[ll].NumJ(); jj++) { + for (auto ii = 0; ii < recombVars[ll].NumI(); ii++) { + dumArr(ii, jj, kk) = recombVars[ll].Residual(ii, jj, kk, 1); + } + } + } + } else if (var == "resid_mom_y") { + for (auto kk = 0; kk < recombVars[ll].NumK(); kk++) { + for (auto jj = 0; jj < recombVars[ll].NumJ(); jj++) { + for (auto ii = 0; ii < recombVars[ll].NumI(); ii++) { + dumArr(ii, jj, kk) = recombVars[ll].Residual(ii, jj, kk, 2); + } + } + } + } else if (var == "resid_mom_z") { + for (auto kk = 0; kk < recombVars[ll].NumK(); kk++) { + for (auto jj = 0; jj < recombVars[ll].NumJ(); jj++) { + for (auto ii = 0; ii < recombVars[ll].NumI(); ii++) { + dumArr(ii, jj, kk) = recombVars[ll].Residual(ii, jj, kk, 3); + } + } + } + } else if (var == "resid_energy") { + for (auto kk = 0; kk < recombVars[ll].NumK(); kk++) { + for (auto jj = 0; jj < recombVars[ll].NumJ(); jj++) { + for (auto ii = 0; ii < recombVars[ll].NumI(); ii++) { + dumArr(ii, jj, kk) = recombVars[ll].Residual(ii, jj, kk, 4); + } + } + } + } else if (var == "resid_tke") { + for (auto kk = 0; kk < recombVars[ll].NumK(); kk++) { + for (auto jj = 0; jj < recombVars[ll].NumJ(); jj++) { + for (auto ii = 0; ii < recombVars[ll].NumI(); ii++) { + dumArr(ii, jj, kk) = recombVars[ll].Residual(ii, jj, kk, 5); + } + } + } + } else if (var == "resid_sdr") { + for (auto kk = 0; kk < recombVars[ll].NumK(); kk++) { + for (auto jj = 0; jj < recombVars[ll].NumJ(); jj++) { + for (auto ii = 0; ii < recombVars[ll].NumI(); ii++) { + dumArr(ii, jj, kk) = recombVars[ll].Residual(ii, jj, kk, 6); + } + } + } } else { - cerr << "ERROR: Variable to write to function file is not defined!" - << endl; - exit(0); + cerr << "ERROR: Variable " << var + << " to write to function file is not defined!" << endl; + exit(EXIT_FAILURE); } // write out dimensional variables -- loop over block length @@ -361,32 +558,53 @@ void WriteFun(const vector &vars, const idealGas &eqnState, for (auto ii = 0; ii < recombVars[ll].NumI(); ii++) { auto dumDouble = dumArr(ii, jj, kk); - if (vv == 0) { // density - dumDouble = dumDouble * inp.RRef(); - } else if (vv == 1) { // velocity x - dumDouble = dumDouble * refSoS; - } else if (vv == 2) { // velocity y - dumDouble = dumDouble * refSoS; - } else if (vv == 3) { // velocity z - dumDouble = dumDouble * refSoS; - } else if (vv == 4) { // pressure - dumDouble = dumDouble * inp.RRef() * refSoS * refSoS; - } else if (vv == 5) { // mach is already nondimensional - dumDouble = dumDouble; - } else if (vv == 6) { // speed of sound - dumDouble = dumDouble * refSoS; - } else if (vv == 7) { // time step - dumDouble = dumDouble / refSoS * inp.LRef(); - } else if (vv == 8) { // temperature - dumDouble = dumDouble * inp.TRef(); - } else if (vv == 12) { // tke - dumDouble = dumDouble * refSoS * refSoS; - } else if (vv == 13) { // omega - dumDouble = dumDouble * refSoS * refSoS * inp.RRef() / - suth.MuRef(); - } else if (vv == 14) { // wall distance - dumDouble = dumDouble * inp.LRef(); + if (var == "density") { + dumDouble *= inp.RRef(); + } else if (var == "vel_x") { + dumDouble *= refSoS; + } else if (var == "vel_y") { + dumDouble *= refSoS; + } else if (var == "vel_z") { + dumDouble *= refSoS; + } else if (var == "pressure") { + dumDouble *= inp.RRef() * refSoS * refSoS; + } else if (var == "sos") { + dumDouble *= refSoS; + } else if (var == "dt") { + dumDouble /= refSoS * inp.LRef(); + } else if (var == "temperature") { + dumDouble *= inp.TRef(); + } else if (var == "tke") { + dumDouble *= refSoS * refSoS; + } else if (var == "sdr") { + dumDouble *= refSoS * refSoS * inp.RRef() / suth.MuRef(); + } else if (var == "wallDistance") { + dumDouble *= inp.LRef(); + } else if (var.find("velGrad_") != string::npos) { + dumDouble *= refSoS / inp.LRef(); + } else if (var.find("tempGrad_") != string::npos) { + dumDouble *= inp.TRef() / inp.LRef(); + } else if (var.find("tkeGrad_") != string::npos) { + dumDouble *= refSoS * refSoS / inp.LRef(); + } else if (var.find("sdrGrad_") != string::npos) { + dumDouble *= refSoS * refSoS * inp.RRef() / + (suth.MuRef() * inp.LRef()); + } else if (var == "resid_mass") { + dumDouble *= inp.RRef() * refSoS * inp.LRef() * inp.LRef(); + } else if (var.find("resid_mom_") != string::npos) { + dumDouble *= inp.RRef() * refSoS * refSoS * inp.LRef() * + inp.LRef(); + } else if (var == "resid_energy") { + dumDouble *= inp.RRef() * pow(refSoS, 3.0) * inp.LRef() * + inp.LRef(); + } else if (var == "resid_tke") { + dumDouble *= inp.RRef() * pow(refSoS, 3.0) * inp.LRef() * + inp.LRef(); + } else if (var == "resid_sdr") { + dumDouble *= inp.RRef() * inp.RRef() * pow(refSoS, 4.0) * + inp.LRef() * inp.LRef() / suth.MuRef(); } + outFile.write(reinterpret_cast(&dumDouble), sizeof(dumDouble)); } @@ -400,30 +618,38 @@ void WriteFun(const vector &vars, const idealGas &eqnState, } // function to write out results file for ensight -void WriteRes(const string &gridName, const int &iter, const int &outFreq) { +void WriteRes(const input &inp, const int &iter) { // open results file const string fResPostfix = ".res"; const string fEnd = "_center"; - const auto resName = gridName + fEnd + fResPostfix; + const auto resName = inp.SimNameRoot() + fEnd + fResPostfix; ofstream resFile(resName, ios::out); + const auto outFreq = inp.OutputFrequency(); + // check to see if file opened correctly if (resFile.fail()) { cerr << "ERROR: Results file " << resName << " did not open correctly!!!" << endl; - exit(0); + exit(EXIT_FAILURE); } const string fPostFix = ".fun"; - const auto writeName = gridName + "_*" + fEnd + fPostFix; - + const auto writeName = inp.SimNameRoot() + "_*" + fEnd + fPostFix; + + const auto outputVars = inp.OutputVariables(); + const auto hasVelVector = outputVars.find("vel_x") != outputVars.end() && + outputVars.find("vel_y") != outputVars.end() && + outputVars.find("vel_z") != outputVars.end(); + + // write number of scalars and number of vectors - constexpr auto numScalar = VAROUT; - auto numVector = 1; + const auto numScalar = inp.NumVarsOutput(); + auto numVector = hasVelVector ? 1 : 0; resFile << numScalar << " " << numVector << " " << 0 << endl; // write number of time points that there is solution data at - auto numTime = iter / outFreq; + auto numTime = iter / outFreq + 1; resFile << numTime << endl; // Write solution times or iteration numbers @@ -442,24 +668,30 @@ void WriteRes(const string &gridName, const int &iter, const int &outFreq) { // Write starting iteration and iteration increment resFile << outFreq << " " << outFreq << endl; - // Write out variables - resFile << writeName << " F 0001 density" << endl; - resFile << writeName << " F 0002 Vx" << endl; - resFile << writeName << " F 0003 Vy" << endl; - resFile << writeName << " F 0004 Vz" << endl; - resFile << writeName << " F 0005 pressure" << endl; - resFile << writeName << " F 0006 mach" << endl; - resFile << writeName << " F 0007 sos" << endl; - resFile << writeName << " F 0008 dt" << endl; - resFile << writeName << " F 0009 temperature" << endl; - resFile << writeName << " F 0010 procRank" << endl; - resFile << writeName << " F 0011 procBlockID" << endl; - resFile << writeName << " F 0012 viscRatio" << endl; - resFile << writeName << " F 0013 tke" << endl; - resFile << writeName << " F 0014 omega" << endl; - resFile << writeName << " F 0015 wallDistance" << endl; - resFile << writeName << " F 0002 0003 0004 velocity" << endl; + // Write out scalar variables + vector3d vectorIndices(0, 0, 0); + auto nvar = 0; + for (auto &var : outputVars) { + resFile << writeName << " F " << std::setfill('0') << setw(4) << nvar + << " " << var << "\n"; + if (var == "vel_x") { + vectorIndices.SetX(nvar); + } else if (var == "vel_y") { + vectorIndices.SetY(nvar); + } else if (var == "vel_z") { + vectorIndices.SetZ(nvar); + } + nvar++; + } + // Write out vector variables + if (hasVelVector) { + resFile << writeName << " F " << std::setfill('0') << setw(4) + << vectorIndices.X() << " " << std::setfill('0') << setw(4) + << vectorIndices.Y() << " " << std::setfill('0') << setw(4) + << vectorIndices.Z() << " velocity\n"; + } + // Close results file resFile.close(); } @@ -586,7 +818,7 @@ int SplitBlockNumber(const vector &vars, const decomposition &decomp, // Get block dimensions (both lower and upper extents) vector, vector3d>> blkDims(vars.size()); vector3d initialLower(0, 0, 0); - for (auto bb = 0; bb < static_cast(blkDims.size()); bb++) { + for (auto bb = 0U; bb < blkDims.size(); bb++) { vector3d dims(vars[bb].NumI(), vars[bb].NumJ(), vars[bb].NumK()); blkDims[bb].first = initialLower; blkDims[bb].second = dims; diff --git a/output.hpp b/output.hpp index 9217d49..142e5c9 100644 --- a/output.hpp +++ b/output.hpp @@ -57,7 +57,7 @@ void WriteCellCenter(const string &, const vector &, void WriteFun(const vector &, const idealGas &, const sutherland &, const int &, const decomposition &, const input &, const unique_ptr &); -void WriteRes(const string &, const int &, const int &); +void WriteRes(const input &, const int &); void WriteResiduals(const input &, genArray &, const genArray &, const resid &, const double &, const int &, const int &, ostream &); diff --git a/parallel.cpp b/parallel.cpp index ade55f3..ca28cd5 100644 --- a/parallel.cpp +++ b/parallel.cpp @@ -55,7 +55,7 @@ decomposition ManualDecomposition(vector &grid, << "number of blocks in the grid. This grid has " << grid.size() << " blocks and the simulation is using " << numProc << " processors." << endl; - exit(0); + exit(EXIT_FAILURE); } cout << "--------------------------------------------------------------------" @@ -63,7 +63,7 @@ decomposition ManualDecomposition(vector &grid, cout << "Using manual grid decomposition." << endl; decomposition decomp(grid.size(), numProc); - for (auto ii = 1; ii < static_cast(grid.size()); ii++) { + for (auto ii = 1U; ii < grid.size(); ii++) { decomp.SendToProc(ii, ROOTP, ii); // send block from ROOT to processor } @@ -108,7 +108,8 @@ decomposition CubicDecomposition(vector &grid, auto idealLoad = decomp.IdealLoad(grid); auto count = 0; - while (decomp.MaxLoad(grid) / idealLoad > 1.1 && count < numProc * 10) { + const auto maxSplits = numProc * 10; + while (decomp.MaxLoad(grid) / idealLoad > 1.1 && count < maxSplits) { auto loaded = 0.0; auto ol = decomp.MostOverloadedProc(grid, loaded); auto ul = decomp.MostUnderloadedProc(grid, loaded); @@ -129,7 +130,7 @@ decomposition CubicDecomposition(vector &grid, auto newBcs = bcs[blk].Split(dir, ind, blk, newBlk, altSurf); bcs.push_back(newBcs); - for (auto ii = 0; ii < static_cast(altSurf.size()); ii++) { + for (auto ii = 0U; ii < altSurf.size(); ii++) { bcs[altSurf[ii].PartnerBlock()].DependentSplit( altSurf[ii], grid[blk], grid[altSurf[ii].PartnerBlock()], altSurf[ii].PartnerBlock(), dir, ind, blk, newBlk); @@ -144,7 +145,7 @@ decomposition CubicDecomposition(vector &grid, count++; } - if (count == numProc * 10 - 1) { + if (count == maxSplits - 1) { cout << "WARNING: Maximum number of splits in decomposition has been " "reached." << endl; } @@ -198,16 +199,18 @@ void SetDataTypesMPI(MPI_Datatype &MPI_vec3d, MPI_Datatype &MPI_cellData, MPI_Datatype &MPI_interblock, MPI_Datatype &MPI_DOUBLE_5INT, MPI_Datatype &MPI_vec3dMag, - MPI_Datatype &MPI_uncoupledScalar) { + MPI_Datatype &MPI_uncoupledScalar, + MPI_Datatype &MPI_tensorDouble) { // MPI_vec3d -- output MPI_Datatype for a vector3d // MPI_cellData -- output MPI_Datatype for primVars or genArray // MPI_procBlockInts -- output MPI_Datatype for 14 INTs (14 INTs in procBlock - // class) + // class) // MPI_interblock -- output MPI_Datatype to send interblock class // MPI_DOUBLE_5INT -- output MPI_Datatype for a double followed by 5 ints // MPI_vec3dMag -- output MPI_Datatype for a unitVect3dMag // MPI_uncoupledScalar -- output MPI_Datatype for a uncoupledScalar - + // MPI_tensorDouble -- output MPI_Datatype for a tensor + // create vector3d MPI datatype MPI_Type_contiguous(3, MPI_DOUBLE, &MPI_vec3d); MPI_Type_commit(&MPI_vec3d); @@ -219,7 +222,11 @@ void SetDataTypesMPI(MPI_Datatype &MPI_vec3d, MPI_Datatype &MPI_cellData, // create uncoupledScalar MPI datatype MPI_Type_contiguous(2, MPI_DOUBLE, &MPI_uncoupledScalar); MPI_Type_commit(&MPI_uncoupledScalar); - + + // create tensor MPI datatype + MPI_Type_contiguous(9, MPI_DOUBLE, &MPI_tensorDouble); + MPI_Type_commit(&MPI_tensorDouble); + // create MPI datatype for states (primVars), residuals (genArray), etc MPI_Type_contiguous(NUMVARS, MPI_DOUBLE, &MPI_cellData); @@ -303,16 +310,18 @@ void FreeDataTypesMPI(MPI_Datatype &MPI_vec3d, MPI_Datatype &MPI_cellData, MPI_Datatype &MPI_interblock, MPI_Datatype &MPI_DOUBLE_5INT, MPI_Datatype &MPI_vec3dMag, - MPI_Datatype &MPI_uncoupledScalar) { + MPI_Datatype &MPI_uncoupledScalar, + MPI_Datatype &MPI_tensorDouble) { // MPI_vec3d -- output MPI_Datatype for a vector3d // MPI_cellData -- output MPI_Datatype for primVars or genArray // MPI_procBlockInts -- output MPI_Datatype for 14 INTs (14 INTs in procBlock - // class) + // class) // MPI_interblock -- output MPI_Datatype to send interblock class // MPI_DOUBLE_5INT -- output MPI_Datatype for a double followed by 5 ints // MPI_vec3dMag -- output MPI_Datatype for a unitVect3dMag // MPI_uncoupledScalar -- output MPI_Datatype for a uncoupledScalar - + // MPI_tensorDouble -- output MPI_Datatype for a tensor + // free vector3d MPI datatype MPI_Type_free(&MPI_vec3d); @@ -324,7 +333,7 @@ void FreeDataTypesMPI(MPI_Datatype &MPI_vec3d, MPI_Datatype &MPI_cellData, // free MPI datatype for uncoupledScalar MPI_Type_free(&MPI_uncoupledScalar); - + // free MPI datatype for all the integers in the procBlock class MPI_Type_free(&MPI_procBlockInts); @@ -349,12 +358,12 @@ vector SendProcBlocks(const vector &blocks, const MPI_Datatype &MPI_vec3d, const MPI_Datatype &MPI_vec3dMag) { // blocks -- full vector of all procBlocks. This is only used on ROOT - // processor, all other processors just need a dummy variable to call the - // function + // processor, all other processors just need a dummy variable to + // call the function // rank -- processor rank. Used to determine if process should send or - // receive + // receive // numProcBlock -- number of procBlocks that the processor should have. (All - // processors may give different values). + // processors may give different values). // MPI_cellData -- MPI_Datatype used for primVars and genArray transmission // MPI_vec3d -- MPI_Datatype used for vector3d transmission // MPI_vec3dMag -- MPI_Datatype used for unitVec3dMag transmission @@ -366,10 +375,10 @@ vector SendProcBlocks(const vector &blocks, // ROOT //------------------------------------------------------------------------ if (rank == ROOTP) { // may have to pack and send data - for (auto ii = 0; ii < static_cast(blocks.size()); - ii++) { // loop over ALL blocks - if (blocks[ii].Rank() == ROOTP) { // no need to send data because it is - // already on ROOT processor + // loop over ALL blocks + for (auto ii = 0U; ii < blocks.size(); ii++) { + // no need to send data because it is already on root processor + if (blocks[ii].Rank() == ROOTP) { localBlocks[blocks[ii].LocalPosition()] = blocks[ii]; } else { // send data to receiving processors // pack and send procBlock @@ -401,29 +410,33 @@ This is used to get all the data on the ROOT processor to write out results. void GetProcBlocks(vector &blocks, const vector &localBlocks, const int &rank, const MPI_Datatype &MPI_cellData, - const MPI_Datatype &MPI_uncoupledScalar) { + const MPI_Datatype &MPI_uncoupledScalar, + const MPI_Datatype &MPI_vec3d, + const MPI_Datatype &MPI_tensorDouble) { // blocks -- full vector of all procBlocks. This is only used on ROOT - // processor, all other processors just need a dummy variable to call the - // function + // processor, all other processors just need a dummy variable to + // call the function // localBlocks -- procBlocks local to each processor. These are sent to ROOT // rank -- processor rank. Used to determine if process should send or - // receive + // receive // MPI_cellData -- MPI_Datatype used for primVars and genArray transmission // MPI_uncoupledScalar -- MPI_Datatype used for uncoupledScalar transmission + // MPI_vec3d -- MPI_Datatype used for vector3d transmission + // MPI_tensorDouble -- MPI_Datatype used for tensor transmission //-------------------------------------------------------------------------- // ROOT //-------------------------------------------------------------------------- if (rank == ROOTP) { // may have to recv and unpack data - for (auto ii = 0; ii < static_cast(blocks.size()); - ii++) { // loop over ALL blocks + for (auto ii = 0U; ii < blocks.size(); ii++) { // loop over ALL blocks if (blocks[ii].Rank() == ROOTP) { // no need to recv data because it is // already on ROOT processor // assign local state block to global state block in order of local // state vector blocks[ii] = localBlocks[blocks[ii].LocalPosition()]; } else { // recv data from sending processors - blocks[ii].RecvUnpackSolMPI(MPI_cellData, MPI_uncoupledScalar); + blocks[ii].RecvUnpackSolMPI(MPI_cellData, MPI_uncoupledScalar, + MPI_vec3d, MPI_tensorDouble); } } //------------------------------------------------------------------------- @@ -432,22 +445,25 @@ void GetProcBlocks(vector &blocks, } else { // pack and send data (non-root) // get vector of local positions vector localPos_(localBlocks.size()); - for (auto ii = 0; ii < static_cast(localPos_.size()); ii++) { + for (auto ii = 0U; ii < localPos_.size(); ii++) { localPos_[ii] = localBlocks[ii].LocalPosition(); } - for (auto ii = 0; ii < static_cast(localBlocks.size()); ii++) { + for (auto ii = 0U; ii < localBlocks.size(); ii++) { // need to send data in order of global position, not local position to // prevent deadlock auto minGlobal = 0; - for (auto jj = 0; jj < static_cast(localPos_.size()); jj++) { + for (auto jj = 0U; jj < localPos_.size(); jj++) { if (localBlocks[localPos_[jj]].GlobalPos() < localBlocks[minGlobal].GlobalPos()) { minGlobal = jj; } } - localBlocks[localPos_[minGlobal]].PackSendSolMPI(MPI_cellData, MPI_uncoupledScalar); + localBlocks[localPos_[minGlobal]].PackSendSolMPI(MPI_cellData, + MPI_uncoupledScalar, + MPI_vec3d, + MPI_tensorDouble); localPos_.erase(localPos_.begin() + minGlobal); } } @@ -510,7 +526,7 @@ double decomposition::IdealLoad(const vector &grid) const { // grid -- vector of plot3dBlocks containing entire grid auto totalCells = 0; - for (auto ii = 0; ii < static_cast(grid.size()); ii++) { + for (auto ii = 0U; ii < grid.size(); ii++) { totalCells += grid[ii].NumCells(); } @@ -525,7 +541,7 @@ double decomposition::MaxLoad(const vector &grid) const { // decomposition) vector load(numProcs_, 0); - for (auto ii = 0; ii < static_cast(grid.size()); ii++) { + for (auto ii = 0U; ii < grid.size(); ii++) { load[rank_[ii]] += grid[ii].NumCells(); } @@ -539,7 +555,7 @@ double decomposition::MinLoad(const vector &grid) const { // decomposition) vector load(numProcs_, 0); - for (auto ii = 0; ii < static_cast(grid.size()); ii++) { + for (auto ii = 0U; ii < grid.size(); ii++) { load[rank_[ii]] += grid[ii].NumCells(); } @@ -555,7 +571,7 @@ int decomposition::MostOverloadedProc(const vector &grid, // overload -- how much the processor is overloaded by vector load(numProcs_, 0); - for (auto ii = 0; ii < static_cast(grid.size()); ii++) { + for (auto ii = 0U; ii < grid.size(); ii++) { load[rank_[ii]] += grid[ii].NumCells(); } @@ -572,7 +588,7 @@ int decomposition::MostUnderloadedProc(const vector &grid, // underload -- how much processor is underloaded by vector load(numProcs_, 0); - for (auto ii = 0; ii < static_cast(grid.size()); ii++) { + for (auto ii = 0U; ii < grid.size(); ii++) { load[rank_[ii]] += grid[ii].NumCells(); } @@ -585,7 +601,7 @@ int decomposition::NumBlocksOnProc(const int &a) const { // a -- processor rank_ to find number of blocks on auto num = 0; - for (auto ii = 0; ii < static_cast(rank_.size()); ii++) { + for (auto ii = 0U; ii < rank_.size(); ii++) { if (rank_[ii] == a) { num++; } @@ -596,7 +612,7 @@ int decomposition::NumBlocksOnProc(const int &a) const { /*Member function to return the number of blocks on all processors.*/ vector decomposition::NumBlocksOnAllProc() const { vector num(numProcs_, 0); - for (auto ii = 0; ii < static_cast(rank_.size()); ii++) { + for (auto ii = 0U; ii < rank_.size(); ii++) { num[rank_[ii]]++; } return num; @@ -621,7 +637,7 @@ void decomposition::SendToProc(const int &blk, const int &fromProc, // all procBlocks on same processor with a local position higher than oldPos // should be moved down one - for (auto ii = 0; ii < static_cast(localPos_.size()); ii++) { + for (auto ii = 0U; ii < localPos_.size(); ii++) { if (rank_[ii] == fromProc && localPos_[ii] > oldPos) { // procBlock is on given processor // and in "higher" position than the @@ -681,7 +697,7 @@ double decomposition::ProcLoad(const vector &grid, // proc -- rank of processor to calculate load for auto load = 0; - for (auto ii = 0; ii < static_cast(grid.size()); ii++) { + for (auto ii = 0U; ii < grid.size(); ii++) { if (rank_[ii] == proc) { load += grid[ii].NumCells(); } @@ -724,7 +740,7 @@ int decomposition::SendWholeOrSplit(const vector &grid, // find out if there is a block that can be sent that would improve both // ratios - for (auto ii = 0; ii < static_cast(grid.size()); ii++) { + for (auto ii = 0U; ii < grid.size(); ii++) { if (rank_[ii] == send) { auto newSendRatio = fabs( 1.0 - (sendLoad - static_cast(grid[ii].NumCells())) / ideal); @@ -740,7 +756,7 @@ int decomposition::SendWholeOrSplit(const vector &grid, // find out which block to split - largest auto bSize = 0; - for (auto ii = 0; ii < static_cast(grid.size()); ii++) { + for (auto ii = 0U; ii < grid.size(); ii++) { if (rank_[ii] == send) { if (grid[ii].NumCells() > bSize) { blk = ii; @@ -792,7 +808,7 @@ int decomposition::SendWholeOrSplit(const vector &grid, void decomposition::PrintDiagnostics(const vector &grid) const { cout << "Decomposition for " << numProcs_ << " processors" << endl; - for (auto ii = 0; ii < static_cast(rank_.size()); ii++) { + for (auto ii = 0U; ii < rank_.size(); ii++) { cout << "Block: " << ii << "; Rank: " << rank_[ii] << ", Parent Block: " << parBlock_[ii] << ", Local Position: " << localPos_[ii] @@ -802,7 +818,7 @@ void decomposition::PrintDiagnostics(const vector &grid) const { << ", Num Cells: " << grid[ii].NumCells() << endl; } cout << "Split History" << endl; - for (auto ii = 0; ii < static_cast(splitHistBlkLow_.size()); ii++) { + for (auto ii = 0U; ii < splitHistBlkLow_.size(); ii++) { cout << "Split Number: " << ii << "; Lower Index: " << splitHistBlkLow_[ii] << ", Upper Index: " << splitHistBlkUp_[ii] diff --git a/parallel.hpp b/parallel.hpp index 8cd5780..2a3a396 100644 --- a/parallel.hpp +++ b/parallel.hpp @@ -53,15 +53,17 @@ void SendNumProcBlocks(const vector&, int&); void SendConnections(vector&, const MPI_Datatype&); void SetDataTypesMPI(MPI_Datatype&, MPI_Datatype&, MPI_Datatype&, MPI_Datatype&, - MPI_Datatype&, MPI_Datatype&, MPI_Datatype&); + MPI_Datatype&, MPI_Datatype&, MPI_Datatype&, + MPI_Datatype&); void FreeDataTypesMPI(MPI_Datatype&, MPI_Datatype&, MPI_Datatype&, MPI_Datatype&, MPI_Datatype&, MPI_Datatype&, - MPI_Datatype&); + MPI_Datatype&, MPI_Datatype&); vector SendProcBlocks(const vector&, const int&, const int&, const MPI_Datatype&, const MPI_Datatype&, const MPI_Datatype&); void GetProcBlocks(vector&, const vector&, const int&, + const MPI_Datatype&, const MPI_Datatype&, const MPI_Datatype&, const MPI_Datatype&); void MaxLinf(resid*, resid*, int*, MPI_Datatype*); diff --git a/plot3d.cpp b/plot3d.cpp index 35c7c20..3521dbe 100644 --- a/plot3d.cpp +++ b/plot3d.cpp @@ -105,7 +105,7 @@ multiArray3d plot3dBlock::Volume() const { cerr << "ERROR: Negative volume in PLOT3D block!!!" << endl; cerr << "i-dim = " << ii << ", j-dim = " << jj << ", k-dim = " << kk << endl; - exit(0); + exit(EXIT_FAILURE); } } } @@ -205,7 +205,7 @@ multiArray3d> plot3dBlock::FaceAreaI() const { << endl; cerr << "Vectors to opposite diagonals are : " << xac << " and " << xbd << endl; - exit(0); + exit(EXIT_FAILURE); } } } @@ -296,7 +296,7 @@ multiArray3d> plot3dBlock::FaceAreaJ() const { << ", k-dim = " << kk << endl; cerr << "Vectors to opposite diagonals are : " << xac << " and " << xbd << endl; - exit(0); + exit(EXIT_FAILURE); } } } @@ -388,7 +388,7 @@ multiArray3d> plot3dBlock::FaceAreaK() const { << ", k-dim = " << kk << endl; cerr << "Vectors to opposite diagonals are : " << xac << " and " << xbd << endl; - exit(0); + exit(EXIT_FAILURE); } } } @@ -442,7 +442,7 @@ vector ReadP3dGrid(const string &gridName, const double &LRef, if (fName.fail()) { cerr << "ERROR: Error in plot3d.cpp:ReadP3dGrid(). Grid file " << readName << " did not open correctly!!!" << endl; - exit(0); + exit(EXIT_FAILURE); } // read the number of plot3d blocks in the file @@ -514,34 +514,6 @@ vector ReadP3dGrid(const string &gridName, const double &LRef, return mesh; } -// function to reorder the block by hyperplanes -/*A hyperplane is a plane of i+j+k=constant within an individual block. The -LUSGS solver must sweep along these hyperplanes to avoid -calculating a flux jacobian. Ex. The solver must visit all points on hyperplane -1 before visiting any points on hyperplane 2. -*/ -vector> HyperplaneReorder(const int &imax, const int &jmax, - const int &kmax) { - // total number of hyperplanes in a given block - const auto numPlanes = imax + jmax + kmax - 2; - vector> reorder; - reorder.reserve(imax * jmax * kmax); - - for (auto pp = 0; pp < numPlanes; pp++) { - for (auto kk = 0; kk < kmax; kk++) { - for (auto jj = 0; jj < jmax; jj++) { - for (auto ii = 0; ii < imax; ii++) { - if (ii + jj + kk == pp) { // if sum of ii, jj, and kk equals pp than - // point is on hyperplane pp - reorder.push_back(vector3d(ii, jj, kk)); - } - } - } - } - } - - return reorder; -} /* Member function to split a plot3dBlock along a plane defined by a direction and an index. @@ -575,7 +547,7 @@ void plot3dBlock::Split(const string &dir, const int &ind, plot3dBlock &blk1, } else { cerr << "ERROR: Error in plot3dBlock::Split(). Direction " << dir << " is not recognized! Choose either i, j, or k." << endl; - exit(0); + exit(EXIT_FAILURE); } } @@ -620,6 +592,6 @@ void plot3dBlock::Join(const plot3dBlock &blk, const string &dir) { } else { cerr << "ERROR: Error in plot3dBlock::Join(). Direction " << dir << " is not recognized! Choose either i, j, or k." << endl; - exit(0); + exit(EXIT_FAILURE); } } diff --git a/plot3d.hpp b/plot3d.hpp index 058d4dc..48c915a 100644 --- a/plot3d.hpp +++ b/plot3d.hpp @@ -41,8 +41,8 @@ class plot3dBlock { explicit plot3dBlock(const multiArray3d> &coordinates) : coords_(coordinates) {} plot3dBlock(const int &ii, const int &jj, const int &kk) : - coords_(multiArray3d>(ii, jj, kk)) {} - plot3dBlock() : coords_(multiArray3d>()) {} + coords_(ii, jj, kk) {} + plot3dBlock() : coords_(1, 1, 1) {} // move constructor and assignment operator plot3dBlock(plot3dBlock&&) noexcept = default; @@ -92,7 +92,5 @@ class plot3dBlock { // function declarations vector ReadP3dGrid(const string &, const double &, double &); -// function to reorder block by hyperplanes -vector> HyperplaneReorder(const int &, const int &, const int &); #endif diff --git a/primVars.cpp b/primVars.cpp index 14769e1..9120778 100644 --- a/primVars.cpp +++ b/primVars.cpp @@ -200,7 +200,7 @@ primVars primVars::FaceReconMUSCL(const primVars &primUW2, invLimiter = limiter / r; } else { cerr << "ERROR: Limiter " << lim << " is not recognized!" << endl; - exit(1); + exit(EXIT_FAILURE); } // calculate reconstructed state at face using MUSCL method with limiter @@ -298,7 +298,8 @@ primVars primVars::GetGhostState(const string &bcType, // suth -- sutherland model for viscosity // turb -- turbulence model // layer -- layer of ghost cell to return (first (closest) or second - // (farthest)) + // (farthest)) + // the instance of primVars being acted upon should be the interior cell // bordering the boundary @@ -310,7 +311,7 @@ primVars primVars::GetGhostState(const string &bcType, cerr << "ERROR: Error in primVars::GetGhostState. Requesting ghost state " "at a ghost layer " << layer << ". Please choose either 1 or 2" << endl; - exit(1); + exit(EXIT_FAILURE); } // face area vector (should always point out of domain) @@ -526,7 +527,7 @@ primVars primVars::GetGhostState(const string &bcType, << endl; cerr << "Interior state: " << (*this) << endl; cerr << "Ghost state: " << ghostState << endl; - exit(1); + exit(EXIT_FAILURE); } if (layer == 2) { // extrapolate to get ghost state at 2nd layer @@ -671,7 +672,7 @@ primVars primVars::GetGhostState(const string &bcType, cerr << "ERROR: Error in primVars::GetGhostState ghost state for BC type " << bcType << " is not supported!" << endl; cerr << "surface is " << surf << endl; - exit(1); + exit(EXIT_FAILURE); } return ghostState; @@ -789,6 +790,16 @@ double primVars::InvCellSpectralRadius(const unitVec3dMag &fAreaL, fMag; } +double primVars::InvFaceSpectralRadius(const unitVec3dMag &fArea, + const idealGas &eqnState) const { + // fArea -- face area + // eqnState -- equation of state + + // return spectral radius + return 0.5 * fArea.Mag() * (fabs(this->Velocity().DotProd(fArea.UnitVector())) + + this->SoS(eqnState)); +} + /*Function to calculate the viscous spectral radius for one direction (i, j, or k). @@ -803,6 +814,7 @@ comes from Blazek. double primVars::ViscCellSpectralRadius( const unitVec3dMag &fAreaL, const unitVec3dMag &fAreaR, const idealGas &eqnState, const sutherland &suth, const double &vol, + const double &mu, const double &mut, const unique_ptr &turb) const { // fAreaL -- face area of lower face in either i, j, or k direction // fAreaR -- face area of upper face in either i, j, or k direction @@ -810,32 +822,59 @@ double primVars::ViscCellSpectralRadius( // suth -- method to the temperature varying visosity and Prandtl number // (Sutherland's law) // vol -- cell volume + // mu -- laminar viscosity + // mut -- turbulent viscosity // turb -- turbulence model // average area magnitude const auto fMag = 0.5 * (fAreaL.Mag() + fAreaR.Mag()); const auto maxTerm = max(4.0 / (3.0 * this->Rho()), eqnState.Gamma() / this->Rho()); - // viscosity at cell center - const auto mu = suth.Viscosity(this->Temperature(eqnState)); + // viscous term const auto viscTerm = suth.NondimScaling() * - (mu / eqnState.Prandtl() + - turb->EddyViscNoLim(*this) / turb->TurbPrandtlNumber()); + (mu / eqnState.Prandtl() + mut / turb->TurbPrandtlNumber()); // return viscous spectral radius return maxTerm * viscTerm * fMag * fMag / vol; } +double primVars::ViscFaceSpectralRadius( + const unitVec3dMag &fArea, + const idealGas &eqnState, const sutherland &suth, const double &dist, + const double &mu, const double &mut, + const unique_ptr &turb) const { + // fArea -- face area + // eqnState -- equation of state + // suth -- method to the temperature varying visosity and Prandtl number + // (Sutherland's law) + // dist -- distacne from cell center to cell center + // mu -- laminar viscosity + // mut -- turbulent viscosity + // turb -- turbulence model + + const auto maxTerm = max(4.0 / (3.0 * this->Rho()), + eqnState.Gamma() / this->Rho()); + // viscous term + const auto viscTerm = suth.NondimScaling() * + (mu / eqnState.Prandtl() + mut / turb->TurbPrandtlNumber()); + + // return viscous spectral radius + return fArea.Mag() / dist * maxTerm * viscTerm; +} + double primVars::CellSpectralRadius( const unitVec3dMag &fAreaL, const unitVec3dMag &fAreaR, const idealGas &eqnState, const sutherland &suth, const double &vol, - const unique_ptr &turb, const bool &isViscous) const { + const double &mu, const double &mut, const unique_ptr &turb, + const bool &isViscous) const { // fAreaL -- face area of lower face in either i, j, or k direction // fAreaR -- face area of upper face in either i, j, or k direction // eqnState -- equation of state // suth -- method to the temperature varying visosity and Prandtl number // (Sutherland's law) // vol -- cell volume + // mu -- laminar viscosity + // mut -- turbulent viscosity // turb -- turbulence model // isViscous -- flag that is true if simulation is viscous @@ -844,7 +883,30 @@ double primVars::CellSpectralRadius( if (isViscous) { // factor 2 2 because viscous spectral radius is not halved (Blazek 6.53) specRad += 2.0 * this->ViscCellSpectralRadius(fAreaL, fAreaR, eqnState, - suth, vol, turb); + suth, vol, mu, mut, turb); + } + return specRad; +} + +double primVars::FaceSpectralRadius(const unitVec3dMag &fArea, + const idealGas &eqnState, const sutherland &suth, const double &dist, + const double &mu, const double &mut, const unique_ptr &turb, + const bool &isViscous) const { + // fAreaL -- face area + // eqnState -- equation of state + // suth -- method to the temperature varying visosity and Prandtl number + // (Sutherland's law) + // dist -- distance from cell center to cell center + // mu -- laminar viscosity + // mut -- turbulent viscosity + // turb -- turbulence model + // isViscous -- flag that is true if simulation is viscous + + auto specRad = this->InvFaceSpectralRadius(fArea, eqnState); + + if (isViscous) { + specRad += this->ViscFaceSpectralRadius(fArea, eqnState, suth, dist, mu, + mut, turb); } return specRad; } diff --git a/primVars.hpp b/primVars.hpp index 12d51ee..7ca9a21 100644 --- a/primVars.hpp +++ b/primVars.hpp @@ -110,14 +110,29 @@ class primVars { double InvCellSpectralRadius(const unitVec3dMag &, const unitVec3dMag &, const idealGas &) const; + double InvFaceSpectralRadius(const unitVec3dMag &, + const idealGas &) const; + double ViscCellSpectralRadius(const unitVec3dMag &, const unitVec3dMag &, const idealGas &, const sutherland &, const double &, + const double &, const double &, const unique_ptr &) const; + double ViscFaceSpectralRadius(const unitVec3dMag &, + const idealGas &, + const sutherland &, const double &, + const double &, const double &, + const unique_ptr &) const; + double CellSpectralRadius(const unitVec3dMag &, const unitVec3dMag &, const idealGas &, - const sutherland &, const double &, - const unique_ptr &, const bool &) const; + const sutherland &, const double &, const double &, + const double &, const unique_ptr &, + const bool &) const; + double FaceSpectralRadius(const unitVec3dMag &, const idealGas &, + const sutherland &, const double &, const double &, + const double &, const unique_ptr &, + const bool &) const; // operator overloads for addition and subtraction of states inline primVars & operator+=(const primVars &); diff --git a/procBlock.cpp b/procBlock.cpp index 0adab53..dd815dc 100644 --- a/procBlock.cpp +++ b/procBlock.cpp @@ -26,12 +26,13 @@ #include "viscousFlux.hpp" // viscousFlux #include "input.hpp" // inputVars #include "turbulence.hpp" -#include "gradients.hpp" #include "slices.hpp" #include "source.hpp" #include "resid.hpp" #include "uncoupledScalar.hpp" #include "fluxJacobian.hpp" +#include "kdtree.hpp" +#include "utility.hpp" using std::cout; using std::endl; @@ -46,8 +47,9 @@ using std::unique_ptr; procBlock::procBlock(const primVars &inputState, const plot3dBlock &blk, const int &numBlk, const int &numG, const boundaryConditions &bound, const int &pos, - const int &r, const int &lpos) { - // inputState -- state_ to initialize block with (primative) + const int &r, const int &lpos, const input &inp, + const idealGas &eos, const sutherland &suth) { + // inputState -- state to initialize block with (primative) // blk -- plot3d block of which this procBlock is a subset of // numBlk -- the block number of blk (the parent block) // numG -- number of ghost cells @@ -65,9 +67,20 @@ procBlock::procBlock(const primVars &inputState, const plot3dBlock &blk, bc_ = bound; + isViscous_ = inp.IsViscous(); + isTurbulent_ = inp.IsTurbulent(); + + // dimensions for multiArray3d located at cell centers with ghost cells + const auto numIG = blk.NumI() - 1 + 2 * numGhosts_; + const auto numJG = blk.NumJ() - 1 + 2 * numGhosts_; + const auto numKG = blk.NumK() - 1 + 2 * numGhosts_; + // dimensions for multiArray3d located at cell centers + const auto numI = blk.NumI() - 1; + const auto numJ = blk.NumJ() - 1; + const auto numK = blk.NumK() - 1; + // pad stored variable vectors with ghost cells - state_ = PadWithGhosts(multiArray3d(blk.NumI() - 1, blk.NumJ() - 1, - blk.NumK() - 1, inputState), + state_ = PadWithGhosts(multiArray3d(numI, numJ, numK, inputState), numGhosts_); vol_ = PadWithGhosts(blk.Volume(), numGhosts_); @@ -79,25 +92,53 @@ procBlock::procBlock(const primVars &inputState, const plot3dBlock &blk, fCenterJ_ = PadWithGhosts(blk.FaceCenterJ(), numGhosts_); fCenterK_ = PadWithGhosts(blk.FaceCenterK(), numGhosts_); - wallDist_ = multiArray3d(blk.NumI() - 1 + 2.0 * numGhosts_, - blk.NumJ() - 1 + 2.0 * numGhosts_, - blk.NumK() - 1 + 2.0 * numGhosts_, - DEFAULTWALLDIST); + wallDist_ = {numIG, numJG, numKG, DEFAULTWALLDIST}; + + specRadius_ = {numI, numJ, numK}; + dt_ = {numI, numJ, numK}; + residual_ = {numI, numJ, numK}; + + const auto inputTemperature = inputState.Temperature(eos); + temperature_ = {numIG, numJG, numKG, inputTemperature}; + + auto inputViscosity = 0.0; + if (isViscous_) { + velocityGrad_ = {numI, numJ, numK}; + temperatureGrad_ = {numI, numJ, numK}; + inputViscosity = suth.Viscosity(inputTemperature); + viscosity_ = {numIG, numJG, numKG, inputViscosity}; + } else { + velocityGrad_ = {1, 1, 1}; + temperatureGrad_ = {1, 1, 1}; + viscosity_ = {1, 1, 1}; + } - specRadius_ = multiArray3d(blk.NumI() - 1, blk.NumJ() - 1, - blk.NumK() - 1); - dt_ = multiArray3d(blk.NumI() - 1, blk.NumJ() - 1, blk.NumK() - 1); - residual_ = multiArray3d(blk.NumI() - 1, blk.NumJ() - 1, - blk.NumK() - 1); + if (isTurbulent_) { + tkeGrad_ = {numI, numJ, numK}; + omegaGrad_ = {numI, numJ, numK}; + eddyViscosity_ = {numIG, numJG, numKG, + inp.FarfieldEddyViscRatio() * inputViscosity}; + f1_ = {numIG, numJG, numKG, 1.0}; + f2_ = {numIG, numJG, numKG, 0.0}; + } else { + tkeGrad_ = {1, 1, 1}; + omegaGrad_ = {1, 1, 1}; + eddyViscosity_ = {1, 1, 1, 0.0}; + f1_ = {1, 1, 1, 0.0}; + f2_ = {1, 1, 1, 0.0}; + } } // constructor -- allocate space for procBlock procBlock::procBlock(const int &ni, const int &nj, const int &nk, - const int &numG) { + const int &numG, const bool &isViscous, + const bool &isTurbulent) { // ni -- i-dimension (cell) // nj -- j-dimension (cell) // nk -- k-dimension (cell) // numG -- number of ghost cell layers + // isViscous -- flag to determine if solution is viscous + // isTurbulent -- flag to determine if solution is turbulent numGhosts_ = numG; parBlock_ = 0; @@ -106,33 +147,57 @@ procBlock::procBlock(const int &ni, const int &nj, const int &nk, globalPos_ = 0; localPos_ = 0; - bc_ = boundaryConditions(); + bc_ = {}; + + isViscous_ = isViscous; + isTurbulent_ = isTurbulent; + + // dimensions including ghost cells + const auto numIG = ni + 2 * numG; + const auto numJG = nj + 2 * numG; + const auto numKG = nk + 2 * numG; // pad stored variable vectors with ghost cells - state_ = multiArray3d(ni + 2 * numG, nj + 2 * numG, nk + 2 * numG); - center_ = multiArray3d>(ni + 2 * numG, nj + 2 * numG, - nk + 2 * numG); - fAreaI_ = multiArray3d>(ni + 2 * numG + 1, - nj + 2 * numG, nk + 2 * numG); - fAreaJ_ = multiArray3d>(ni + 2 * numG, - nj + 2 * numG + 1, - nk + 2 * numG); - fAreaK_ = multiArray3d>(ni + 2 * numG, - nj + 2 * numG, - nk + 2 * numG + 1); - fCenterI_ = multiArray3d>(ni + 2 * numG + 1, nj + 2 * numG, - nk + 2 * numG); - fCenterJ_ = multiArray3d>(ni + 2 * numG, nj + 2 * numG + 1, - nk + 2 * numG); - fCenterK_ = multiArray3d>(ni + 2 * numG, nj + 2 * numG, - nk + 2 * numG + 1); - residual_ = multiArray3d(ni, nj, nk); - vol_ = multiArray3d(ni + 2 * numG, nj + 2 * numG, nk + 2 * numG); - wallDist_ = multiArray3d(ni + 2 * numG, nj + 2 * numG, nk + 2 * numG, - DEFAULTWALLDIST); - - specRadius_ = multiArray3d(ni, nj, nk); - dt_ = multiArray3d(ni, nj, nk); + state_ = {numIG, numJG, numKG}; + center_ = {numIG, numJG, numKG}; + fAreaI_ = {numIG + 1, numJG, numKG}; + fAreaJ_ = {numIG, numJG + 1, numKG}; + fAreaK_ = {numIG, numJG, numKG + 1}; + fCenterI_ = {numIG + 1, numJG, numKG}; + fCenterJ_ = {numIG, numJG + 1, numKG}; + fCenterK_ = {numIG, numJG, numKG + 1}; + residual_ = {ni, nj, nk}; + vol_ = {numIG, numJG, numKG}; + wallDist_ = {numIG, numJG, numKG, DEFAULTWALLDIST}; + + specRadius_ = {ni, nj, nk}; + dt_ = {ni, nj, nk}; + + temperature_ = {numIG, numJG, numKG}; + + if (isViscous_) { + velocityGrad_ = {ni, nj, nk}; + temperatureGrad_ = {ni, nj, nk}; + viscosity_ = {numIG, numJG, numKG}; + } else { + velocityGrad_ = {1, 1, 1}; + temperatureGrad_ = {1, 1, 1}; + viscosity_ = {1, 1, 1}; + } + + if (isTurbulent_) { + tkeGrad_ = {ni, nj, nk}; + omegaGrad_ = {ni, nj, nk}; + eddyViscosity_ = {numIG, numJG, numKG}; + f1_ = {numIG, numJG, numKG}; + f2_ = {numIG, numJG, numKG}; + } else { + tkeGrad_ = {1, 1, 1}; + omegaGrad_ = {1, 1, 1}; + eddyViscosity_ = {1, 1, 1}; + f1_ = {1, 1, 1}; + f2_ = {1, 1, 1}; + } } // member function to add a member of the inviscid flux class to the residual @@ -302,40 +367,52 @@ void procBlock::CalcInvFluxI(const idealGas &eqnState, const input &inp, inp.Kappa(), inp.Limiter(), upwindU, upwind2U, downwindU); } // calculate Roe flux at face - const inviscidFlux tempFlux = RoeFlux( - faceStateLower, faceStateUpper, eqnState, - this->FAreaUnitI(ig, jg, kg)); - + const inviscidFlux tempFlux = RoeFlux(faceStateLower, faceStateUpper, + eqnState, + this->FAreaUnitI(ig, jg, kg)); + // area vector points from left to right, so add to left cell, subtract // from right cell // at left boundary there is no left cell to add to if (ig > numGhosts_) { this->AddToResidual(tempFlux * this->FAreaMagI(ig, jg, kg), ip - 1, jp, kp); + + // if using a block matrix on main diagonal, accumulate flux jacobian + if (inp.IsBlockMatrix()) { + fluxJacobian fluxJac; + fluxJac.RusanovFluxJacobian(faceStateLower, eqnState, + this->FAreaI(ig, jg, kg), true, + inp, turb); + mainDiagonal(ip - 1, jp, kp) += fluxJac; + } } + // at right boundary there is no right cell to add to if (ig < fAreaI_.NumI() - numGhosts_ - 1) { this->SubtractFromResidual(tempFlux * this->FAreaMagI(ig, jg, kg), ip, jp, kp); + // calculate component of wave speed. This is done on a cell by cell // basis, so only at the upper faces const auto invSpecRad = state_(ig, jg, kg).InvCellSpectralRadius( fAreaI_(ig, jg, kg), fAreaI_(ig + 1, jg, kg), eqnState); - const auto turbInvSpecRad = inp.IsTurbulent() ? - turb->InviscidSpecRad(state_(ig, jg, kg), fAreaI_(ig, jg, kg), - fAreaI_(ig + 1, jg, kg)): 0.0; + const auto turbInvSpecRad = isTurbulent_ ? + turb->InviscidCellSpecRad(state_(ig, jg, kg), fAreaI_(ig, jg, kg), + fAreaI_(ig + 1, jg, kg)): 0.0; const uncoupledScalar specRad(invSpecRad, turbInvSpecRad); specRadius_(ip, jp, kp) += specRad; - // if using a block matrix on main diagonal, calculate flux jacobian + // if using a block matrix on main diagonal, accumulate flux jacobian if (inp.IsBlockMatrix()) { - // fluxJacobian fluxJac; - // fluxJac.RusanovFluxJacobian(state_(ig - 1, jg, kg), state_(ig, jg, kg), - // eqnState, fAreaI_(ig, jg, kg), true, inp); - // mainDiagonal(ip, jp, kp) += fluxJac; + fluxJacobian fluxJac; + fluxJac.RusanovFluxJacobian(faceStateUpper, eqnState, + this->FAreaI(ig, jg, kg), false, + inp, turb); + mainDiagonal(ip, jp, kp) -= fluxJac; } else { mainDiagonal(ip, jp, kp) += fluxJacobian(specRad); } @@ -432,31 +509,41 @@ void procBlock::CalcInvFluxJ(const idealGas &eqnState, const input &inp, if (jg > numGhosts_) { this->AddToResidual(tempFlux * this->FAreaMagJ(ig, jg, kg), ip, jp - 1, kp); + + // if using block matrix on main diagonal, calculate flux jacobian + if (inp.IsBlockMatrix()) { + fluxJacobian fluxJac; + fluxJac.RusanovFluxJacobian(faceStateLower, eqnState, + this->FAreaJ(ig, jg, kg), true, + inp, turb); + mainDiagonal(ip, jp - 1, kp) += fluxJac; + } } // at right boundary no right cell to add to if (jg < fAreaJ_.NumJ() - numGhosts_ - 1) { this->SubtractFromResidual(tempFlux * this->FAreaMagJ(ig, jg, kg), ip, jp, kp); - + // calculate component of wave speed. This is done on a cell by cell // basis, so only at the upper faces const auto invSpecRad = state_(ig, jg, kg).InvCellSpectralRadius( fAreaJ_(ig, jg, kg), fAreaJ_(ig, jg + 1, kg), eqnState); - const auto turbInvSpecRad = inp.IsTurbulent() ? - turb->InviscidSpecRad(state_(ig, jg, kg), fAreaJ_(ig, jg, kg), - fAreaJ_(ig, jg + 1, kg)): 0.0; + const auto turbInvSpecRad = isTurbulent_ ? + turb->InviscidCellSpecRad(state_(ig, jg, kg), fAreaJ_(ig, jg, kg), + fAreaJ_(ig, jg + 1, kg)): 0.0; const uncoupledScalar specRad(invSpecRad, turbInvSpecRad); - specRadius_ += specRad; + specRadius_(ip, jp, kp) += specRad; // if using block matrix on main diagonal, calculate flux jacobian if (inp.IsBlockMatrix()) { - // mainDiagonal(ip, jp, kp).AddInviscidJacobian( - // state_(ig, jg, kg), fAreaJ_(ig, jg, kg), - // fAreaJ_(ig, jg + 1, kg), eqnState, turb, - // inp.IsTurbulent()); + fluxJacobian fluxJac; + fluxJac.RusanovFluxJacobian(faceStateUpper, eqnState, + this->FAreaJ(ig, jg, kg), false, + inp, turb); + mainDiagonal(ip, jp, kp) -= fluxJac; } else { mainDiagonal(ip, jp, kp) += fluxJacobian(specRad); } @@ -554,6 +641,15 @@ void procBlock::CalcInvFluxK(const idealGas &eqnState, const input &inp, this->AddToResidual(tempFlux * this->FAreaMagK(ig, jg, kg), ip, jp, kp - 1); + + // if using block matrix on main diagonal, calculate flux jacobian + if (inp.IsBlockMatrix()) { + fluxJacobian fluxJac; + fluxJac.RusanovFluxJacobian(faceStateLower, eqnState, + this->FAreaK(ig, jg, kg), true, + inp, turb); + mainDiagonal(ip, jp, kp - 1) += fluxJac; + } } // at right boundary no right cell to add to if (kg < fAreaK_.NumK() - numGhosts_ - 1) { @@ -566,19 +662,20 @@ void procBlock::CalcInvFluxK(const idealGas &eqnState, const input &inp, const auto invSpecRad = state_(ig, jg, kg).InvCellSpectralRadius( fAreaK_(ig, jg, kg), fAreaK_(ig, jg, kg + 1), eqnState); - const auto turbInvSpecRad = inp.IsTurbulent() ? - turb->InviscidSpecRad(state_(ig, jg, kg), fAreaK_(ig, jg, kg), - fAreaK_(ig + 1, jg, kg + 1)) : 0.0; + const auto turbInvSpecRad = isTurbulent_ ? + turb->InviscidCellSpecRad(state_(ig, jg, kg), fAreaK_(ig, jg, kg), + fAreaK_(ig, jg, kg + 1)) : 0.0; const uncoupledScalar specRad(invSpecRad, turbInvSpecRad); specRadius_(ip, jp, kp) += specRad; // if using block matrix on main diagonal, calculate flux jacobian if (inp.IsBlockMatrix()) { - // mainDiagonal(ip, jp, kp).AddInviscidJacobian( - // state_(ig, jg, kg), fAreaK_(ig, jg, kg), - // fAreaK_(ig, jg, kg + 1), eqnState, turb, - // inp.IsTurbulent()); + fluxJacobian fluxJac; + fluxJac.RusanovFluxJacobian(faceStateUpper, eqnState, + this->FAreaK(ig, jg, kg), false, + inp, turb); + mainDiagonal(ip, jp, kp) -= fluxJac; } else { mainDiagonal(ip, jp, kp) += fluxJacobian(specRad); } @@ -607,9 +704,9 @@ void procBlock::CalcCellDt(const int &ii, const int &jj, const int &kk, // cfl -- cfl number // use nondimensional time - dt_(ii, jj, kk) = cfl * (vol_(ii + numGhosts_, jj + numGhosts_, - kk + numGhosts_) / - specRadius_(ii, jj, kk).FlowVariable()); + dt_(ii, jj, kk) = cfl * + (vol_(ii + numGhosts_, jj + numGhosts_, kk + numGhosts_) / + specRadius_(ii, jj, kk).Max()); } /* Member function to calculate the time step for all cells in the procBlock. If @@ -635,7 +732,7 @@ void procBlock::CalcBlockTimeStep(const input &inputVars, const double &aRef) { this->CalcCellDt(ii, jj, kk, inputVars.CFL()); } else { cerr << "ERROR: Neither dt or cfl was specified!" << endl; - exit(1); + exit(EXIT_FAILURE); } } } @@ -670,17 +767,14 @@ void procBlock::UpdateBlock(const input &inputVars, const idealGas &eos, for (auto ip = 0, ig = numGhosts_; ip < this->NumI(); ig++, ip++) { // explicit euler time integration if (inputVars.TimeIntegration() == "explicitEuler") { - this->ExplicitEulerTimeAdvance(eos, turb, ig, jg, kg, - ip, jp, kp); + this->ExplicitEulerTimeAdvance(eos, turb, ig, jg, kg, ip, jp, kp); // 4-stage runge-kutta method (explicit) } else if (inputVars.TimeIntegration() == "rk4") { // advance 1 RK stage this->RK4TimeAdvance(consVars(ip, jp, kp), eos, turb, - ig, jg, kg, - ip, jp, kp, rr); + ig, jg, kg, ip, jp, kp, rr); } else if (inputVars.IsImplicit()) { // if implicit use update (du) - this->ImplicitTimeAdvance(du(ig, jg, kg), eos, turb, - ig, jg, kg); + this->ImplicitTimeAdvance(du(ig, jg, kg), eos, turb, ig, jg, kg); } else { cerr << "ERROR: Time integration scheme " << inputVars.TimeIntegration() << " is not recognized!" << endl; @@ -702,7 +796,7 @@ void procBlock::UpdateBlock(const input &inputVars, const idealGas &eos, } } -/* Member function to advance the state_ vector to time n+1 using explicit Euler +/* Member function to advance the state vector to time n+1 using explicit Euler method. The following equation is used: Un+1 = Un - dt_/V * R @@ -739,8 +833,8 @@ void procBlock::ExplicitEulerTimeAdvance(const idealGas &eqnState, void procBlock::ImplicitTimeAdvance(const genArray &du, const idealGas &eqnState, const unique_ptr &turb, - const int &ii, - const int &jj, const int &kk) { + const int &ii, const int &jj, + const int &kk) { // du -- update for a specific cell (to move from time n to n+1) // eqnState -- equation of state // turb -- turbulence model @@ -794,8 +888,27 @@ void procBlock::RK4TimeAdvance(const genArray &currState, // iteration. This is done because the residual and wave // speed are accumulated over many function calls. void procBlock::ResetResidWS() { - residual_.Zero(genArray(0.0)); - specRadius_.Zero(uncoupledScalar(0.0, 0.0)); + residual_.Zero(); + specRadius_.Zero(); +} + +// member function to reset the gradients back to zero after an +// iteration. This is done because the gradients are accumulated over many +// function calls. +void procBlock::ResetGradients() { + velocityGrad_.Zero(); + temperatureGrad_.Zero(); + tkeGrad_.Zero(); + omegaGrad_.Zero(); +} + +// member function to reset the turbulence variables back to zero after an +// iteration. This is done because these variables are accumulated over many +// function calls. +void procBlock::ResetTurbVars() { + eddyViscosity_.Zero(0.0); + f1_.Zero(0.0); + f2_.Zero(0.0); } /* Member function to add the cell volume divided by the cell time step to the @@ -846,8 +959,7 @@ multiArray3d procBlock::SolTimeMMinusN( for (auto ip = 0, ig = numGhosts_; ip < this->NumI(); ig++, ip++) { const auto diagVolTime = (vol_(ig, jg, kg) * (1.0 + inp.Zeta())) / (dt_(ip, jp, kp) * inp.Theta()); - mMinusN(ip, jp, kp) = - diagVolTime * (m(ip, jp, kp) - n(ip, jp, kp)); + mMinusN(ip, jp, kp) = diagVolTime * (m(ip, jp, kp) - n(ip, jp, kp)); } } } @@ -924,16 +1036,15 @@ void procBlock::InvertDiagonal(multiArray3d &mainDiagonal, (dt_(ip, jp, kp) * inp.Theta()); if (inp.DualTimeCFL() > 0.0) { // use dual time stepping // equal to volume / tau - diagVolTime += specRadius_(ip, jp, kp).FlowVariable() / + diagVolTime += specRadius_(ip, jp, kp).Max() / inp.DualTimeCFL(); } // add volume and time term - mainDiagonal(ip, jp, kp) *= inp.MatrixRelaxation(); - mainDiagonal(ip, jp, kp) += diagVolTime; - - // invert main diagonal - mainDiagonal(ip, jp, kp).Inverse(inp.IsTurbulent()); + mainDiagonal(ip, jp, kp).MultiplyOnDiagonal(inp.MatrixRelaxation(), + isTurbulent_); + mainDiagonal(ip, jp, kp).AddOnDiagonal(diagVolTime, isTurbulent_); + mainDiagonal(ip, jp, kp).Inverse(isTurbulent_); } } } @@ -953,8 +1064,7 @@ multiArray3d procBlock::GetCopyConsVars( for (auto jp = 0, jg = numGhosts_; jp < this->NumJ(); jg++, jp++) { for (auto ip = 0, ig = numGhosts_; ip < this->NumI(); ig++, ip++) { // convert state to conservative variables - consVars(ip, jp, kp) = - state_(ig, jg, kg).ConsVars(eqnState); + consVars(ip, jp, kp) = state_(ig, jg, kg).ConsVars(eqnState); } } } @@ -1109,11 +1219,17 @@ void procBlock::LUSGS_Forward(const vector> &reorder, // from it if (this->IsPhysical(ip - 1, jp, kp, false) || bc_.GetBCName(ip, jp, kp, "il") == "interblock") { + // calculate projected center to center distance along face area + const auto projDist = this->ProjC2CDist(ig, jg, kg, "i"); + // update L matrix - L += RusanovOffDiagonal(state_(ig - 1, jg, kg), x(ig - 1 , jg, kg), - fAreaI_(ig, jg, kg), fAreaI_(ig - 1, jg, kg), - vol_(ig - 1, jg, kg), eqnState, suth, turb, - inp, true); + L += OffDiagonal(state_(ig - 1, jg, kg), state_(ig, jg, kg), + x(ig - 1 , jg, kg), fAreaI_(ig, jg, kg), + this->Viscosity(ig - 1, jg, kg), + this->EddyViscosity(ig - 1, jg, kg), + this->F1(ig - 1, jg, kg), projDist, + this->VelGrad(ip - 1, jp, kp), + eqnState, suth, turb, inp, true); } // ----------------------------------------------------------------------- @@ -1121,11 +1237,17 @@ void procBlock::LUSGS_Forward(const vector> &reorder, // from it if (this->IsPhysical(ip, jp - 1, kp, false) || bc_.GetBCName(ip, jp, kp, "jl") == "interblock") { + // calculate projected center to center distance along face area + const auto projDist = this->ProjC2CDist(ig, jg, kg, "j"); + // update L matrix - L += RusanovOffDiagonal(state_(ig, jg - 1, kg), x(ig, jg - 1, kg), - fAreaJ_(ig, jg, kg), fAreaJ_(ig, jg - 1, kg), - vol_(ig, jg - 1, kg), eqnState, suth, turb, - inp, true); + L += OffDiagonal(state_(ig, jg - 1, kg), state_(ig, jg, kg), + x(ig, jg - 1, kg), fAreaJ_(ig, jg, kg), + this->Viscosity(ig, jg - 1, kg), + this->EddyViscosity(ig, jg - 1, kg), + this->F1(ig, jg - 1, kg), projDist, + this->VelGrad(ip, jp - 1, kp), + eqnState, suth, turb, inp, true); } // ----------------------------------------------------------------------- @@ -1133,11 +1255,17 @@ void procBlock::LUSGS_Forward(const vector> &reorder, // from it if (this->IsPhysical(ip, jp, kp - 1, false) || bc_.GetBCName(ip, jp, kp, "kl") == "interblock") { + // calculate projected center to center distance along face area + const auto projDist = this->ProjC2CDist(ig, jg, kg, "k"); + // update L matrix - L += RusanovOffDiagonal(state_(ig, jg, kg - 1), x(ig, jg, kg - 1), - fAreaK_(ig, jg, kg), fAreaK_(ig, jg, kg - 1), - vol_(ig, jg, kg - 1), eqnState, suth, turb, - inp, true); + L += OffDiagonal(state_(ig, jg, kg - 1), state_(ig, jg, kg), + x(ig, jg, kg - 1), fAreaK_(ig, jg, kg), + this->Viscosity(ig, jg, kg - 1), + this->EddyViscosity(ig, jg, kg - 1), + this->F1(ig, jg, kg - 1), projDist, + this->VelGrad(ip, jp, kp - 1), + eqnState, suth, turb, inp, true); } @@ -1151,12 +1279,17 @@ void procBlock::LUSGS_Forward(const vector> &reorder, // from it if (this->IsPhysical(ip + 1, jp, kp, false) || bc_.GetBCName(ip + 1, jp, kp, "iu") == "interblock") { + // calculate projected center to center distance along face area + const auto projDist = this->ProjC2CDist(ig + 1, jg, kg, "i"); + // update U matrix - U += RusanovOffDiagonal(state_(ig + 1, jg, kg), x(ig + 1 , jg, kg), - fAreaI_(ig + 1, jg, kg), - fAreaI_(ig + 2, jg, kg), - vol_(ig + 1, jg, kg), eqnState, suth, turb, - inp, false); + U += OffDiagonal(state_(ig + 1, jg, kg), state_(ig, jg, kg), + x(ig + 1 , jg, kg), fAreaI_(ig + 1, jg, kg), + this->Viscosity(ig + 1, jg, kg), + this->EddyViscosity(ig + 1, jg, kg), + this->F1(ig + 1, jg, kg), projDist, + this->VelGrad(ip + 1, jp, kp), + eqnState, suth, turb, inp, false); } // ----------------------------------------------------------------------- @@ -1164,12 +1297,17 @@ void procBlock::LUSGS_Forward(const vector> &reorder, // from it if (this->IsPhysical(ip, jp + 1, kp, false) || bc_.GetBCName(ip, jp + 1, kp, "ju") == "interblock") { + // calculate projected center to center distance along face area + const auto projDist = this->ProjC2CDist(ig, jg + 1, kg, "j"); + // update U matrix - U += RusanovOffDiagonal(state_(ig, jg + 1, kg), x(ig, jg + 1, kg), - fAreaJ_(ig, jg + 1, kg), - fAreaJ_(ig, jg + 2, kg), - vol_(ig, jg + 1, kg), eqnState, suth, turb, - inp, false); + U += OffDiagonal(state_(ig, jg + 1, kg), state_(ig, jg, kg), + x(ig, jg + 1, kg), fAreaJ_(ig, jg + 1, kg), + this->Viscosity(ig, jg + 1, kg), + this->EddyViscosity(ig, jg + 1, kg), + this->F1(ig, jg + 1, kg), projDist, + this->VelGrad(ip, jp + 1, kp), + eqnState, suth, turb, inp, false); } // ----------------------------------------------------------------------- @@ -1177,12 +1315,17 @@ void procBlock::LUSGS_Forward(const vector> &reorder, // from it if (this->IsPhysical(ip, jp, kp + 1, false) || bc_.GetBCName(ip, jp, kp + 1, "ku") == "interblock") { + // calculate projected center to center distance along face area + const auto projDist = this->ProjC2CDist(ig, jg, kg + 1, "k"); + // update U matrix - U += RusanovOffDiagonal(state_(ig, jg, kg + 1), x(ig, jg, kg + 1), - fAreaK_(ig, jg, kg + 1), - fAreaK_(ig, jg, kg + 2), - vol_(ig, jg, kg + 1), eqnState, suth, turb, - inp, false); + U += OffDiagonal(state_(ig, jg, kg + 1), state_(ig, jg, kg), + x(ig, jg, kg + 1), fAreaK_(ig, jg, kg + 1), + this->Viscosity(ig, jg, kg + 1), + this->EddyViscosity(ig, jg, kg + 1), + this->F1(ig, jg, kg + 1), projDist, + this->VelGrad(ip, jp, kp + 1), + eqnState, suth, turb, inp, false); } } // ----------------------------------------------------------------------- @@ -1243,11 +1386,17 @@ double procBlock::LUSGS_Backward(const vector> &reorder, // from it if (this->IsPhysical(ip + 1, jp, kp, false) || bc_.GetBCName(ip + 1, jp, kp, "iu") == "interblock") { + // calculate projected center to center distance along face area + const auto projDist = this->ProjC2CDist(ig + 1, jg, kg, "i"); + // update U matrix - U += RusanovOffDiagonal(state_(ig + 1, jg, kg), x(ig + 1, jg, kg), - fAreaI_(ig + 1, jg, kg), fAreaI_(ig + 2, jg, kg), - vol_(ig + 1, jg, kg), eqnState, suth, turb, - inp, false); + U += OffDiagonal(state_(ig + 1, jg, kg), state_(ig, jg, kg), + x(ig + 1, jg, kg), fAreaI_(ig + 1, jg, kg), + this->Viscosity(ig + 1, jg, kg), + this->EddyViscosity(ig + 1, jg, kg), + this->F1(ig + 1, jg, kg), projDist, + this->VelGrad(ip + 1, jp, kp), + eqnState, suth, turb, inp, false); } // ----------------------------------------------------------------------- @@ -1255,11 +1404,17 @@ double procBlock::LUSGS_Backward(const vector> &reorder, // from it if (this->IsPhysical(ip, jp + 1, kp, false) || bc_.GetBCName(ip, jp + 1, kp, "ju") == "interblock") { + // calculate projected center to center distance along face area + const auto projDist = this->ProjC2CDist(ig, jg + 1, kg, "j"); + // update U matrix - U += RusanovOffDiagonal(state_(ig, jg + 1, kg), x(ig, jg + 1, kg), - fAreaJ_(ig, jg + 1, kg), fAreaJ_(ig, jg + 2, kg), - vol_(ig, jg + 1, kg), eqnState, suth, turb, - inp, false); + U += OffDiagonal(state_(ig, jg + 1, kg), state_(ig, jg, kg), + x(ig, jg + 1, kg), fAreaJ_(ig, jg + 1, kg), + this->Viscosity(ig, jg + 1, kg), + this->EddyViscosity(ig, jg + 1, kg), + this->F1(ig, jg + 1, kg), projDist, + this->VelGrad(ip, jp + 1, kp), + eqnState, suth, turb, inp, false); } // ----------------------------------------------------------------------- @@ -1267,11 +1422,17 @@ double procBlock::LUSGS_Backward(const vector> &reorder, // from it if (this->IsPhysical(ip, jp, kp + 1, false) || bc_.GetBCName(ip, jp, kp + 1, "ku") == "interblock") { + // calculate projected center to center distance along face area + const auto projDist = this->ProjC2CDist(ig, jg, kg + 1, "k"); + // update U matrix - U += RusanovOffDiagonal(state_(ig, jg, kg + 1), x(ig, jg, kg + 1), - fAreaK_(ig, jg, kg + 1), fAreaK_(ig, jg, kg + 2), - vol_(ig, jg, kg + 1), eqnState, suth, turb, - inp, false); + U += OffDiagonal(state_(ig, jg, kg + 1), state_(ig, jg, kg), + x(ig, jg, kg + 1), fAreaK_(ig, jg, kg + 1), + this->Viscosity(ig, jg, kg + 1), + this->EddyViscosity(ig, jg, kg + 1), + this->F1(ig, jg, kg + 1), projDist, + this->VelGrad(ip, jp, kp + 1), + eqnState, suth, turb, inp, false); } @@ -1285,11 +1446,17 @@ double procBlock::LUSGS_Backward(const vector> &reorder, // from it if (this->IsPhysical(ip - 1, jp, kp, false) || bc_.GetBCName(ip, jp, kp, "il") == "interblock") { + // calculate projected center to center distance along face area + const auto projDist = this->ProjC2CDist(ig, jg, kg, "i"); + // update U matrix - L += RusanovOffDiagonal(state_(ig - 1, jg, kg), x(ig - 1, jg, kg), - fAreaI_(ig, jg, kg), fAreaI_(ig - 1, jg, kg), - vol_(ig - 1, jg, kg), eqnState, suth, turb, - inp, true); + L += OffDiagonal(state_(ig - 1, jg, kg), state_(ig, jg, kg), + x(ig - 1, jg, kg), fAreaI_(ig, jg, kg), + this->Viscosity(ig - 1, jg, kg), + this->EddyViscosity(ig - 1, jg, kg), + this->F1(ig - 1, jg, kg), projDist, + this->VelGrad(ip - 1, jp, kp), + eqnState, suth, turb, inp, true); } // ----------------------------------------------------------------------- @@ -1297,11 +1464,17 @@ double procBlock::LUSGS_Backward(const vector> &reorder, // from it if (this->IsPhysical(ip, jp - 1, kp, false) || bc_.GetBCName(ip, jp, kp, "jl") == "interblock") { + // calculate projected center to center distance along face area + const auto projDist = this->ProjC2CDist(ig, jg, kg, "j"); + // update U matrix - L += RusanovOffDiagonal(state_(ig, jg - 1, kg), x(ig, jg - 1, kg), - fAreaJ_(ig, jg, kg), fAreaJ_(ig, jg - 1, kg), - vol_(ig, jg - 1, kg), eqnState, suth, turb, - inp, true); + L += OffDiagonal(state_(ig, jg - 1, kg), state_(ig, jg, kg), + x(ig, jg - 1, kg), fAreaJ_(ig, jg, kg), + this->Viscosity(ig, jg - 1, kg), + this->EddyViscosity(ig, jg - 1, kg), + this->F1(ig, jg - 1, kg), projDist, + this->VelGrad(ip, jp - 1, kp), + eqnState, suth, turb, inp, true); } // ----------------------------------------------------------------------- @@ -1309,11 +1482,17 @@ double procBlock::LUSGS_Backward(const vector> &reorder, // from it if (this->IsPhysical(ip, jp, kp - 1, false) || bc_.GetBCName(ip, jp, kp, "kl") == "interblock") { + // calculate projected center to center distance along face area + const auto projDist = this->ProjC2CDist(ig, jg, kg, "k"); + // update U matrix - L += RusanovOffDiagonal(state_(ig, jg, kg - 1), x(ig, jg, kg - 1), - fAreaK_(ig, jg, kg), fAreaK_(ig, jg, kg - 1), - vol_(ig, jg, kg - 1), eqnState, suth, turb, - inp, true); + L += OffDiagonal(state_(ig, jg, kg - 1), state_(ig, jg, kg), + x(ig, jg, kg - 1), fAreaK_(ig, jg, kg), + this->Viscosity(ig, jg, kg - 1), + this->EddyViscosity(ig, jg, kg - 1), + this->F1(ig, jg, kg - 1), projDist, + this->VelGrad(ip, jp, kp - 1), + eqnState, suth, turb, inp, true); } } // ----------------------------------------------------------------------- @@ -1375,25 +1554,17 @@ double procBlock::DPLUR(multiArray3d &x, // contribution from it if (this->IsPhysical(ip - 1, jp, kp, false) || bc_.GetBCName(ip, jp, kp, "il") == "interblock") { + // calculate projected center to center distance + const auto projDist = this->ProjC2CDist(ig, jg, kg, "i"); + // update off diagonal - if (inp.InvFluxJac() == "rusanov") { - offDiagonal += - RusanovOffDiagonal(state_(ig - 1, jg, kg), xold(ig - 1, jg, kg), - fAreaI_(ig, jg, kg), fAreaI_(ig - 1, jg, kg), - vol_(ig - 1, jg, kg), eqnState, suth, turb, - inp, true); - } else if (inp.InvFluxJac() == "approximateRoe") { - offDiagonal += - RoeOffDiagonal(state_(ig - 1, jg, kg), state_(ig, jg, kg), - xold(ig - 1, jg, kg), fAreaI_(ig, jg, kg), - fAreaI_(ig - 1, jg, kg), vol_(ig - 1, jg, kg), - eqnState, suth, turb, inp, true); - } else { - cerr << "ERROR: Error in procBlock::DPLUR, inviscid flux " << - "jacobian method of " << inp.InvFluxJac() << - " is not recognized!" << endl; - exit(1); - } + offDiagonal += OffDiagonal(state_(ig - 1, jg, kg), state_(ig, jg, kg), + xold(ig - 1, jg, kg), fAreaI_(ig, jg, kg), + this->Viscosity(ig - 1, jg, kg), + this->EddyViscosity(ig - 1, jg, kg), + this->F1(ig - 1, jg, kg), projDist, + this->VelGrad(ip - 1, jp, kp), + eqnState, suth, turb, inp, true); } // -------------------------------------------------------------- @@ -1401,25 +1572,17 @@ double procBlock::DPLUR(multiArray3d &x, // constribution from it if (this->IsPhysical(ip, jp - 1, kp, false) || bc_.GetBCName(ip, jp, kp, "jl") == "interblock") { + // calculate projected center to center distance + const auto projDist = this->ProjC2CDist(ig, jg, kg, "j"); + // update off diagonal - if (inp.InvFluxJac() == "rusanov") { - offDiagonal += - RusanovOffDiagonal(state_(ig, jg - 1, kg), xold(ig, jg - 1, kg), - fAreaJ_(ig, jg, kg), fAreaJ_(ig, jg - 1, kg), - vol_(ig, jg - 1, kg), eqnState, suth, turb, - inp, true); - } else if (inp.InvFluxJac() == "approximateRoe") { - offDiagonal += - RoeOffDiagonal(state_(ig, jg - 1, kg), state_(ig, jg, kg), - xold(ig, jg - 1, kg), fAreaJ_(ig, jg, kg), - fAreaJ_(ig, jg - 1, kg), vol_(ig, jg - 1, kg), - eqnState, suth, turb, inp, true); - } else { - cerr << "ERROR: Error in procBlock::DPLUR, inviscid flux " << - "jacobian method of " << inp.InvFluxJac() << - " is not recognized!" << endl; - exit(1); - } + offDiagonal += OffDiagonal(state_(ig, jg - 1, kg), state_(ig, jg, kg), + xold(ig, jg - 1, kg), fAreaJ_(ig, jg, kg), + this->Viscosity(ig, jg - 1 , kg), + this->EddyViscosity(ig, jg - 1 , kg), + this->F1(ig, jg - 1 , kg), projDist, + this->VelGrad(ip, jp - 1, kp), + eqnState, suth, turb, inp, true); } // -------------------------------------------------------------- @@ -1427,26 +1590,17 @@ double procBlock::DPLUR(multiArray3d &x, // contribution from it if (this->IsPhysical(ip, jp, kp - 1, false) || bc_.GetBCName(ip, jp, kp, "kl") == "interblock") { + // calculate projected center to center distance + const auto projDist = this->ProjC2CDist(ig, jg, kg, "k"); + // update off diagonal - if (inp.InvFluxJac() == "rusanov") { - offDiagonal += - RusanovOffDiagonal(state_(ig, jg, kg - 1), xold(ig, jg, kg - 1), - fAreaK_(ig, jg, kg), fAreaK_(ig, jg, kg - 1), - vol_(ig, jg, kg - 1), eqnState, suth, turb, - inp, true); - } else if (inp.InvFluxJac() == "approximateRoe") { - offDiagonal += - RoeOffDiagonal(state_(ig, jg, kg - 1), state_(ig, jg, kg), - xold(ig, jg, kg - 1), - fAreaK_(ig, jg, kg), fAreaK_(ig, jg, kg - 1), - vol_(ig, jg, kg - 1), eqnState, suth, turb, - inp, true); - } else { - cerr << "ERROR: Error in procBlock::DPLUR, inviscid flux " << - "jacobian method of " << inp.InvFluxJac() << - " is not recognized!" << endl; - exit(1); - } + offDiagonal += OffDiagonal(state_(ig, jg, kg - 1), state_(ig, jg, kg), + xold(ig, jg, kg - 1), fAreaK_(ig, jg, kg), + this->Viscosity(ig, jg, kg - 1), + this->EddyViscosity(ig, jg, kg - 1), + this->F1(ig, jg, kg - 1), projDist, + this->VelGrad(ip, jp, kp - 1), + eqnState, suth, turb, inp, true); } // -------------------------------------------------------------- @@ -1454,27 +1608,18 @@ double procBlock::DPLUR(multiArray3d &x, // contribution from it if (this->IsPhysical(ip + 1, jp, kp, false) || bc_.GetBCName(ip + 1, jp, kp, "iu") == "interblock") { + // calculate projected center to center distance + const auto projDist = this->ProjC2CDist(ig + 1, jg, kg, "i"); + // update off diagonal - if (inp.InvFluxJac() == "rusanov") { - offDiagonal -= - RusanovOffDiagonal(state_(ig + 1, jg, kg), xold(ig + 1, jg, kg), - fAreaI_(ig + 1, jg, kg), - fAreaI_(ig + 2, jg, kg), - vol_(ig + 1, jg, kg), eqnState, suth, turb, - inp, false); - } else if (inp.InvFluxJac() == "approximateRoe") { - offDiagonal -= - RoeOffDiagonal(state_(ig + 1, jg, kg), state_(ig, jg, kg), - xold(ig + 1, jg, kg), - fAreaI_(ig + 1, jg, kg), fAreaI_(ig + 2, jg, kg), - vol_(ig + 1, jg, kg), eqnState, suth, turb, - inp, false); - } else { - cerr << "ERROR: Error in procBlock::DPLUR, inviscid flux " << - "jacobian method of " << inp.InvFluxJac() << - " is not recognized!" << endl; - exit(1); - } + offDiagonal -= OffDiagonal(state_(ig + 1, jg, kg), state_(ig, jg, kg), + xold(ig + 1, jg, kg), + fAreaI_(ig + 1, jg, kg), + this->Viscosity(ig + 1, jg, kg), + this->EddyViscosity(ig + 1, jg, kg), + this->F1(ig + 1, jg, kg), projDist, + this->VelGrad(ip + 1, jp, kp), + eqnState, suth, turb, inp, false); } // -------------------------------------------------------------- @@ -1482,27 +1627,18 @@ double procBlock::DPLUR(multiArray3d &x, // contribution from it if (this->IsPhysical(ip, jp + 1, kp, false) || bc_.GetBCName(ip, jp + 1, kp, "ju") == "interblock") { + // calculate projected center to center distance + const auto projDist = this->ProjC2CDist(ig, jg + 1, kg, "j"); + // update off diagonal - if (inp.InvFluxJac() == "rusanov") { - offDiagonal -= - RusanovOffDiagonal(state_(ig, jg + 1, kg), xold(ig, jg + 1, kg), - fAreaJ_(ig, jg + 1, kg), - fAreaJ_(ig, jg + 2, kg), - vol_(ig, jg + 1, kg), eqnState, suth, turb, - inp, false); - } else if (inp.InvFluxJac() == "approximateRoe") { - offDiagonal -= - RoeOffDiagonal(state_(ig, jg + 1, kg), state_(ig, jg, kg), - xold(ig, jg + 1, kg), - fAreaJ_(ig, jg + 1, kg), fAreaJ_(ig, jg + 2, kg), - vol_(ig, jg + 1, kg), eqnState, suth, turb, - inp, false); - } else { - cerr << "ERROR: Error in procBlock::DPLUR, inviscid flux " << - "jacobian method of " << inp.InvFluxJac() << - " is not recognized!" << endl; - exit(1); - } + offDiagonal -= OffDiagonal(state_(ig, jg + 1, kg), state_(ig, jg, kg), + xold(ig, jg + 1, kg), + fAreaJ_(ig, jg + 1, kg), + this->Viscosity(ig, jg + 1, kg), + this->EddyViscosity(ig, jg + 1, kg), + this->F1(ig, jg + 1, kg), projDist, + this->VelGrad(ip, jp + 1, kp), + eqnState, suth, turb, inp, false); } // -------------------------------------------------------------- @@ -1510,27 +1646,18 @@ double procBlock::DPLUR(multiArray3d &x, // contribution from it if (this->IsPhysical(ip, jp, kp + 1, false) || bc_.GetBCName(ip, jp, kp + 1, "ku") == "interblock") { + // calculate projected center to center distance + const auto projDist = this->ProjC2CDist(ig, jg, kg + 1, "k"); + // update off diagonal - if (inp.InvFluxJac() == "rusanov") { - offDiagonal -= - RusanovOffDiagonal(state_(ig, jg, kg + 1), xold(ig, jg, kg + 1), - fAreaK_(ig, jg, kg + 1), - fAreaK_(ig, jg, kg + 2), - vol_(ig, jg, kg + 1), eqnState, suth, turb, - inp, false); - } else if (inp.InvFluxJac() == "approximateRoe") { - offDiagonal -= - RoeOffDiagonal(state_(ig, jg, kg + 1), state_(ig, jg, kg), - xold(ig, jg, kg + 1), - fAreaK_(ig, jg, kg + 1), fAreaK_(ig, jg, kg + 2), - vol_(ig, jg, kg + 1), eqnState, suth, turb, - inp, false); - } else { - cerr << "ERROR: Error in procBlock::DPLUR, inviscid flux " << - "jacobian method of " << inp.InvFluxJac() << - " is not recognized!" << endl; - exit(1); - } + offDiagonal -= OffDiagonal(state_(ig, jg, kg + 1), state_(ig, jg, kg), + xold(ig, jg, kg + 1), + fAreaK_(ig, jg, kg + 1), + this->Viscosity(ig, jg, kg + 1), + this->EddyViscosity(ig, jg, kg + 1), + this->F1(ig, jg, kg + 1), projDist, + this->VelGrad(ip, jp, kp + 1), + eqnState, suth, turb, inp, false); } // -------------------------------------------------------------- @@ -1582,30 +1709,7 @@ multiArray3d procBlock::InitializeMatrixUpdate(const input &inp, } -// function to reconstruct cell variables to the face using central -// differences -template -T FaceReconCentral(const T &varU, const T &varD, const vector3d &pU, - const vector3d &pD, const vector3d &pF) { - // varU -- variable at the cell center of the upwind cell - // varD -- variable at the cell center of the downwind cell - // pU -- position of the cell center of the upwind cell - // pD -- position of the cell center of the downwind cell - // pF -- position of the face center of the face on which the reconstruction - // is happening - - // distance from cell center to cell center - const auto cen2cen = pU.Distance(pD); - // distance from upwind cell center to cell face - const auto up2face = pU.Distance(pF); - // ratio of distance from upwind cell center to cell face to center to center - const auto upRatio = up2face / cen2cen; - - // reconstruct with central difference - return varD * upRatio + varU * (1.0 - upRatio); -} - -/* Function to pad a vector with a specified number of ghost cells +/* Function to pad a multiArray3d with a specified number of ghost cells ___ ___ ___ ___ ___ ___ ___ ___ | E | E | G | G | G | G | E | E | |___|___|___|___|___|___|___|___| @@ -1645,154 +1749,6 @@ multiArray3d PadWithGhosts(const multiArray3d &var, return padBlk; } -/* Function to calculate the velocity gradient at the cell center using the -Green-Gauss method - -dU/dxj = (Sum) U * Aij / V (j=1,2,3) - i=1,nfaces - -The above equation shows how the gradient of a scalar is calculated using the -Green-Gauss method. U is a scalar. Aij is the area at face i (component j). -V is the volume of the control volume. X is the cartesian direction with -j indicating the component. The convention is for the area vectors to point out -of the control volume. - */ -tensor CalcVelGradGG( - const vector3d &vil, const vector3d &viu, - const vector3d &vjl, const vector3d &vju, - const vector3d &vkl, const vector3d &vku, - const vector3d &ail, const vector3d &aiu, - const vector3d &ajl, const vector3d &aju, - const vector3d &akl, const vector3d &aku, - const double &vol) { - // vil -- velocity vector at the i-lower face of the cell at which the - // velocity gradient is being calculated - // viu -- velocity vector at the i-upper face of the cell at which the - // velocity gradient is being calculated - // vjl -- velocity vector at the j-lower face of the cell at which the - // velocity gradient is being calculated - // vju -- velocity vector at the j-upper face of the cell at which the - // velocity gradient is being calculated - // vkl -- velocity vector at the k-lower face of the cell at which the - // velocity gradient is being calculated - // vku -- velocity vector at the k-upper face of the cell at which the - // velocity gradient is being calculated - - // ail -- area vector at the lower i-face of the cell at which the velocity - // gradient is being calculated - // aiu -- area vector at the upper i-face of the cell at which the velocity - // gradient is being calculated - // ajl -- area vector at the lower j-face of the cell at which the velocity - // gradient is being calculated - // aju -- area vector at the upper j-face of the cell at which the velocity - // gradient is being calculated - // akl -- area vector at the lower k-face of the cell at which the velocity - // gradient is being calculated - // aku -- area vector at the upper k-face of the cell at which the velocity - // gradient is being calculated - - // vol -- cell volume - - tensor temp; - const auto invVol = 1.0 / vol; - - // define velocity gradient tensor - // convention is for area vector to point out of cell, so lower values are - // negative, upper are positive - temp.SetXX(invVol * - (viu.X() * aiu.X() - vil.X() * ail.X() + vju.X() * aju.X() - - vjl.X() * ajl.X() + vku.X() * aku.X() - vkl.X() * akl.X())); - temp.SetXY(invVol * - (viu.Y() * aiu.X() - vil.Y() * ail.X() + vju.Y() * aju.X() - - vjl.Y() * ajl.X() + vku.Y() * aku.X() - vkl.Y() * akl.X())); - temp.SetXZ(invVol * - (viu.Z() * aiu.X() - vil.Z() * ail.X() + vju.Z() * aju.X() - - vjl.Z() * ajl.X() + vku.Z() * aku.X() - vkl.Z() * akl.X())); - - temp.SetYX(invVol * - (viu.X() * aiu.Y() - vil.X() * ail.Y() + vju.X() * aju.Y() - - vjl.X() * ajl.Y() + vku.X() * aku.Y() - vkl.X() * akl.Y())); - temp.SetYY(invVol * - (viu.Y() * aiu.Y() - vil.Y() * ail.Y() + vju.Y() * aju.Y() - - vjl.Y() * ajl.Y() + vku.Y() * aku.Y() - vkl.Y() * akl.Y())); - temp.SetYZ(invVol * - (viu.Z() * aiu.Y() - vil.Z() * ail.Y() + vju.Z() * aju.Y() - - vjl.Z() * ajl.Y() + vku.Z() * aku.Y() - vkl.Z() * akl.Y())); - - temp.SetZX(invVol * - (viu.X() * aiu.Z() - vil.X() * ail.Z() + vju.X() * aju.Z() - - vjl.X() * ajl.Z() + vku.X() * aku.Z() - vkl.X() * akl.Z())); - temp.SetZY(invVol * - (viu.Y() * aiu.Z() - vil.Y() * ail.Z() + vju.Y() * aju.Z() - - vjl.Y() * ajl.Z() + vku.Y() * aku.Z() - vkl.Y() * akl.Z())); - temp.SetZZ(invVol * - (viu.Z() * aiu.Z() - vil.Z() * ail.Z() + vju.Z() * aju.Z() - - vjl.Z() * ajl.Z() + vku.Z() * aku.Z() - vkl.Z() * akl.Z())); - - return temp; -} - -/* Function to calculate the gradient of a scalar at the cell center using the -Green-Gauss method - -dU/dxj = (Sum) U * Aij / V (j=1,2,3) - i=1,nfaces - -The above equation shows how the gradient of a scalar is calculated using the -Green-Gauss method. U is a scalar. Aij is the area at face i (component j). -V is the volume of the control volume. X is the cartesian direction with -j indicating the component. The convention is for the area vectors to point out -of the control volume. - */ -vector3d CalcScalarGradGG( - const double &til, const double &tiu, const double &tjl, const double &tju, - const double &tkl, const double &tku, const vector3d &ail, - const vector3d &aiu, const vector3d &ajl, - const vector3d &aju, const vector3d &akl, - const vector3d &aku, const double &vol) { - // til -- scalar value at the lower face of the cell at which the scalar - // gradient is being calculated - // tiu -- scalar value at the upper face of the cell at which the scalar - // gradient is being calculated - // tjl -- scalar value at the lower face of the cell at which the scalar - // gradient is being calculated - // tju -- scalar value at the upper face of the cell at which the scalar - // gradient is being calculated - // tkl -- scalar value at the lower face of the cell at which the scalar - // gradient is being calculated - // tku -- scalar value at the upper face of the cell at which the scalar - // gradient is being calculated - - // ail -- area vector at the lower face of the cell at which the scalar - // gradient is being calculated - // aiu -- area vector at the upper face of the cell at which the scalar - // gradient is being calculated - // ajl -- area vector at the lower face of the cell at which the scalar - // gradient is being calculated - // aju -- area vector at the upper face of the cell at which the scalar - // gradient is being calculated - // akl -- area vector at the lower face of the cell at which the scalar - // gradient is being calculated - // aku -- area vector at the upper face of the cell at which the scalar - // gradient is being calculated - - // vol -- cell volume - - vector3d temp; - const auto invVol = 1.0 / vol; - - // define scalar gradient vector - // convention is for area vector to point out of cell, so lower values are - // negative, upper are positive - temp.SetX(invVol * (tiu * aiu.X() - til * ail.X() + tju * aju.X() - - tjl * ajl.X() + tku * aku.X() - tkl * akl.X())); - temp.SetY(invVol * (tiu * aiu.Y() - til * ail.Y() + tju * aju.Y() - - tjl * ajl.Y() + tku * aku.Y() - tkl * akl.Y())); - temp.SetZ(invVol * (tiu * aiu.Z() - til * ail.Z() + tju * aju.Z() - - tjl * ajl.Z() + tku * aku.Z() - tkl * akl.Z())); - - return temp; -} /* Function to calculate the viscous fluxes on the i-faces. All phyiscal (non-ghost) i-faces are looped over. The left and right states are @@ -1864,7 +1820,7 @@ touches 15 cells. The gradient calculation with this stencil uses the "edge" ghost cells, but not the "corner" ghost cells. */ void procBlock::CalcViscFluxI(const sutherland &suth, const idealGas &eqnState, - const input &inp, const gradients &grads, + const input &inp, const unique_ptr &turb, multiArray3d &mainDiagonal) { // suth -- method to get viscosity as a function of temperature (Sutherland's @@ -1878,7 +1834,8 @@ void procBlock::CalcViscFluxI(const sutherland &suth, const idealGas &eqnState, // implicit solver const auto viscCoeff = inp.ViscousCFLCoefficient(); - + constexpr auto sixth = 1.0 / 6.0; + // loop over all physical i-faces for (auto kp = 0, kg = numGhosts_; kg < fAreaI_.NumK() - numGhosts_; kg++, kp++) { @@ -1887,12 +1844,11 @@ void procBlock::CalcViscFluxI(const sutherland &suth, const idealGas &eqnState, for (auto ip = 0, ig = numGhosts_; ig < fAreaI_.NumI() - numGhosts_; ig++, ip++) { // Get state at face - auto state = - FaceReconCentral(state_(ig - 1, jg, kg), - state_(ig, jg, kg), - center_(ig - 1, jg, kg), - center_(ig, jg, kg), - fCenterI_(ig, jg, kg)); + auto state = FaceReconCentral(state_(ig - 1, jg, kg), + state_(ig, jg, kg), + center_(ig - 1, jg, kg), + center_(ig, jg, kg), + fCenterI_(ig, jg, kg)); state.LimitTurb(turb); // Get wall distance at face @@ -1902,17 +1858,35 @@ void procBlock::CalcViscFluxI(const sutherland &suth, const idealGas &eqnState, center_(ig, jg, kg), fCenterI_(ig, jg, kg)); - // calculate viscous flux - vector3d tkeGrad, omegaGrad; - if (inp.IsTurbulent()) { - tkeGrad = grads.TkeGradI(ip, jp, kp); - omegaGrad = grads.OmegaGradI(ip, jp, kp); + // Get viscosity at face + const auto mu = FaceReconCentral(viscosity_(ig - 1, jg, kg), + viscosity_(ig, jg, kg), + center_(ig - 1, jg, kg), + center_(ig, jg, kg), + fCenterI_(ig, jg, kg)); + + // calculate gradients + tensor velGrad; + vector3d tempGrad, tkeGrad, omegaGrad; + CalcGradsI(ig, jg, kg, velGrad, tempGrad, tkeGrad, omegaGrad); + + // calculate turbulent eddy viscosity and blending coefficients + auto f1 = 0.0; + auto f2 = 0.0; + auto mut = 0.0; + if (isTurbulent_) { + turb->EddyViscAndBlending(state, velGrad, tkeGrad, omegaGrad, mu, + wDist, suth, mut, f1, f2); } - const viscousFlux tempViscFlux(grads.VelGradI(ip, jp, kp), suth, - eqnState, - grads.TempGradI(ip, jp, kp), + + // calculate viscous flux + const viscousFlux tempViscFlux(velGrad, suth, eqnState, tempGrad, this->FAreaUnitI(ig, jg, kg), - tkeGrad, omegaGrad, turb, state, wDist); + tkeGrad, omegaGrad, turb, state, mu, + mut, f1); + + // calculate projected center to center distance + const auto c2cDist = this->ProjC2CDist(ig, jg, kg, "i"); // area vector points from left to right, so add to left cell, subtract // from right cell but viscous fluxes are subtracted from inviscid @@ -1922,6 +1896,27 @@ void procBlock::CalcViscFluxI(const sutherland &suth, const idealGas &eqnState, this->SubtractFromResidual(tempViscFlux * this->FAreaMagI(ig, jg, kg), ip - 1, jp, kp); + + // store gradients + velocityGrad_(ip - 1, jp, kp) += sixth * velGrad; + temperatureGrad_(ip - 1, jp, kp) += sixth * tempGrad; + if (isTurbulent_) { + tkeGrad_(ip - 1, jp, kp) += sixth * tkeGrad; + omegaGrad_(ip - 1, jp, kp) += sixth * omegaGrad; + eddyViscosity_(ig - 1, jg, kg) += sixth * mut; + f1_(ig - 1, jg, kg) += sixth * f1; + f2_(ig - 1, jg, kg) += sixth * f2; + } + + // if using block matrix on main diagonal, accumulate flux jacobian + if (inp.IsBlockMatrix()) { + // using mu, mut, and f1 at face + fluxJacobian fluxJac; + fluxJac.ApproxTSLJacobian(state, mu, mut, f1, eqnState, suth, + this->FAreaI(ig, jg, kg), c2cDist, + turb, inp, true, velGrad); + mainDiagonal(ip - 1, jp, kp) -= fluxJac; + } } // at right boundary there is no right cell to add to if (ig < fAreaI_.NumI() - numGhosts_ - 1) { @@ -1929,28 +1924,42 @@ void procBlock::CalcViscFluxI(const sutherland &suth, const idealGas &eqnState, this->FAreaMagI(ig, jg, kg), ip, jp, kp); + // store gradients + velocityGrad_(ip, jp, kp) += sixth * velGrad; + temperatureGrad_(ip, jp, kp) += sixth * tempGrad; + if (isTurbulent_) { + tkeGrad_(ip, jp, kp) += sixth * tkeGrad; + omegaGrad_(ip, jp, kp) += sixth * omegaGrad; + eddyViscosity_(ig, jg, kg) += sixth * mut; + f1_(ig, jg, kg) += sixth * f1; + f2_(ig, jg, kg) += sixth * f2; + } + // calculate component of wave speed. This is done on a cell by cell // basis, so only at the upper faces const auto viscSpecRad = state_(ig, jg, kg).ViscCellSpectralRadius( fAreaI_(ig, jg, kg), fAreaI_(ig + 1, jg, kg), eqnState, suth, - vol_(ig, jg, kg), turb); + vol_(ig, jg, kg), viscosity_(ig, jg, kg), mut, turb); - const auto turbViscSpecRad = inp.IsTurbulent() ? - turb->ViscSpecRad(state_(ig, jg, kg), fAreaI_(ig, jg, kg), - fAreaI_(ig + 1, jg, kg), eqnState, suth, - vol_(ig, jg, kg)) : 0.0; + const auto turbViscSpecRad = isTurbulent_ ? + turb->ViscCellSpecRad(state_(ig, jg, kg), fAreaI_(ig, jg, kg), + fAreaI_(ig + 1, jg, kg), + viscosity_(ig, jg, kg), + suth, vol_(ig, jg, kg), mut, f1) + : 0.0; const uncoupledScalar specRad(viscSpecRad, turbViscSpecRad); specRadius_(ip, jp, kp) += specRad * viscCoeff; - - // if using block matrix on main diagonal, calculate flux jacobian + // if using block matrix on main diagonal, accumulate flux jacobian if (inp.IsBlockMatrix()) { - // mainDiagonal(ip, jp, kp).AddViscousJacobian( - // state_(ig, jg, kg), fAreaI_(ig, jg, kg), - // fAreaI_(ig + 1, jg, kg), eqnState, suth, - // vol_(ig, jg, kg), turb, inp.IsTurbulent()); + // using mu, mut, and f1 at face + fluxJacobian fluxJac; + fluxJac.ApproxTSLJacobian(state, mu, mut, f1, eqnState, suth, + this->FAreaI(ig, jg, kg), c2cDist, + turb, inp, false, velGrad); + mainDiagonal(ip, jp, kp) += fluxJac; } else { // factor 2 because visc spectral radius is not halved (Blazek 6.53) mainDiagonal(ip, jp, kp) += fluxJacobian(2.0 * specRad); @@ -2033,7 +2042,7 @@ faces in a cell touches 15 cells. The gradient calculation with this stencil use the "edge" ghost cells, but not the "corner" ghost cells. */ void procBlock::CalcViscFluxJ(const sutherland &suth, const idealGas &eqnState, - const input &inp, const gradients &grads, + const input &inp, const unique_ptr &turb, multiArray3d &mainDiagonal) { // suth -- method to get viscosity as a function of temperature (Sutherland's @@ -2047,6 +2056,7 @@ void procBlock::CalcViscFluxJ(const sutherland &suth, const idealGas &eqnState, // implicit solver const auto viscCoeff = inp.ViscousCFLCoefficient(); + constexpr auto sixth = 1.0 / 6.0; // loop over all physical j-faces for (auto kp = 0, kg = numGhosts_; kg < fAreaJ_.NumK() - numGhosts_; @@ -2056,12 +2066,11 @@ void procBlock::CalcViscFluxJ(const sutherland &suth, const idealGas &eqnState, for (auto ip = 0, ig = numGhosts_; ig < fAreaJ_.NumI() - numGhosts_; ig++, ip++) { // Get velocity at face - auto state = - FaceReconCentral(state_(ig, jg - 1, kg), - state_(ig, jg, kg), - center_(ig, jg - 1, kg), - center_(ig, jg, kg), - fCenterJ_(ig, jg, kg)); + auto state = FaceReconCentral(state_(ig, jg - 1, kg), + state_(ig, jg, kg), + center_(ig, jg - 1, kg), + center_(ig, jg, kg), + fCenterJ_(ig, jg, kg)); state.LimitTurb(turb); // Get wall distance at face @@ -2071,17 +2080,36 @@ void procBlock::CalcViscFluxJ(const sutherland &suth, const idealGas &eqnState, center_(ig, jg, kg), fCenterJ_(ig, jg, kg)); - // calculate viscous flux - vector3d tkeGrad, omegaGrad; - if (inp.IsTurbulent()) { - tkeGrad = grads.TkeGradJ(ip, jp, kp); - omegaGrad = grads.OmegaGradJ(ip, jp, kp); + // Get wall distance at face + const auto mu = FaceReconCentral(viscosity_(ig, jg - 1, kg), + viscosity_(ig, jg, kg), + center_(ig, jg - 1, kg), + center_(ig, jg, kg), + fCenterJ_(ig, jg, kg)); + + // calculate gradients + tensor velGrad; + vector3d tempGrad, tkeGrad, omegaGrad; + CalcGradsJ(ig, jg, kg, velGrad, tempGrad, tkeGrad, omegaGrad); + + // calculate turbulent eddy viscosity and blending coefficients + auto f1 = 0.0; + auto f2 = 0.0; + auto mut = 0.0; + if (isTurbulent_) { + turb->EddyViscAndBlending(state, velGrad, tkeGrad, omegaGrad, mu, + wDist, suth, mut, f1, f2); } - const viscousFlux tempViscFlux(grads.VelGradJ(ip, jp, kp), suth, - eqnState, - grads.TempGradJ(ip, jp, kp), + + // calculate viscous flux + const viscousFlux tempViscFlux(velGrad, suth, eqnState, tempGrad, this->FAreaUnitJ(ig, jg, kg), - tkeGrad, omegaGrad, turb, state, wDist); + tkeGrad, omegaGrad, turb, state, mu, + mut, f1); + + // calculate projected center to center distance + const auto c2cDist = this->ProjC2CDist(ig, jg, kg, "j"); + // area vector points from left to right, so add to left cell, subtract // from right cell but viscous fluxes are subtracted from inviscid @@ -2091,6 +2119,27 @@ void procBlock::CalcViscFluxJ(const sutherland &suth, const idealGas &eqnState, this->SubtractFromResidual(tempViscFlux * this->FAreaMagJ(ig, jg, kg), ip, jp - 1, kp); + + // store gradients + velocityGrad_(ip, jp - 1, kp) += sixth * velGrad; + temperatureGrad_(ip, jp - 1, kp) += sixth * tempGrad; + if (isTurbulent_) { + tkeGrad_(ip, jp - 1, kp) += sixth * tkeGrad; + omegaGrad_(ip, jp - 1, kp) += sixth * omegaGrad; + eddyViscosity_(ig, jg - 1, kg) += sixth * mut; + f1_(ig, jg - 1, kg) += sixth * f1; + f2_(ig, jg - 1, kg) += sixth * f2; + } + + // if using block matrix on main diagonal, accumulate flux jacobian + if (inp.IsBlockMatrix()) { + // using mu, mut, and f1 at face + fluxJacobian fluxJac; + fluxJac.ApproxTSLJacobian(state, mu, mut, f1, eqnState, suth, + this->FAreaJ(ig, jg, kg), c2cDist, + turb, inp, true, velGrad); + mainDiagonal(ip, jp - 1, kp) -= fluxJac; + } } // at right boundary there is no right cell to add to if (jg < fAreaJ_.NumJ() - numGhosts_ - 1) { @@ -2098,28 +2147,43 @@ void procBlock::CalcViscFluxJ(const sutherland &suth, const idealGas &eqnState, this->FAreaMagJ(ig, jg, kg), ip, jp, kp); + // store gradients + velocityGrad_(ip, jp, kp) += sixth * velGrad; + temperatureGrad_(ip, jp, kp) += sixth * tempGrad; + if (isTurbulent_) { + tkeGrad_(ip, jp, kp) += sixth * tkeGrad; + omegaGrad_(ip, jp, kp) += sixth * omegaGrad; + eddyViscosity_(ig, jg, kg) += sixth * mut; + f1_(ig, jg, kg) += sixth * f1; + f2_(ig, jg, kg) += sixth * f2; + } + // calculate component of wave speed. This is done on a cell by cell // basis, so only at the upper faces const auto viscSpecRad = state_(ig, jg, kg).ViscCellSpectralRadius( fAreaJ_(ig, jg, kg), fAreaJ_(ig, jg + 1, kg), eqnState, suth, - vol_(ig, jg, kg), turb); + vol_(ig, jg, kg), viscosity_(ig, jg, kg), mut, turb); - const auto turbViscSpecRad = inp.IsTurbulent() ? - turb->ViscSpecRad(state_(ig, jg, kg), fAreaJ_(ig, jg, kg), - fAreaJ_(ig, jg + 1, kg), eqnState, suth, - vol_(ig, jg, kg)) : 0.0; + const auto turbViscSpecRad = isTurbulent_ ? + turb->ViscCellSpecRad(state_(ig, jg, kg), fAreaJ_(ig, jg, kg), + fAreaJ_(ig, jg + 1, kg), + viscosity_(ig, jg, kg), + suth, vol_(ig, jg, kg), mut, f1) + : 0.0; const uncoupledScalar specRad(viscSpecRad, turbViscSpecRad); specRadius_(ip, jp, kp) += specRad * viscCoeff; - // if using block matrix on main diagonal, calculate flux jacobian + // if using block matrix on main diagonal, accumulate flux jacobian if (inp.IsBlockMatrix()) { - // mainDiagonal(ip, jp, kp).AddViscousJacobian( - // state_(ig, jg, kg), fAreaJ_(ig, jg, kg), - // fAreaJ_(ig, jg + 1, kg), eqnState, suth, - // vol_(ig, jg, kg), turb, inp.IsTurbulent()); + // using mu, mut, and f1 at face + fluxJacobian fluxJac; + fluxJac.ApproxTSLJacobian(state, mu, mut, f1, eqnState, suth, + this->FAreaJ(ig, jg, kg), c2cDist, + turb, inp, false, velGrad); + mainDiagonal(ip, jp, kp) += fluxJac; } else { // factor 2 because visc spectral radius is not halved (Blazek 6.53) mainDiagonal(ip, jp, kp) += fluxJacobian(2.0 * specRad); @@ -2201,7 +2265,7 @@ faces in a cell touches 15 cells. The gradient calculation with this stencil use the "edge" ghost cells, but not the "corner" ghost cells. */ void procBlock::CalcViscFluxK(const sutherland &suth, const idealGas &eqnState, - const input &inp, const gradients &grads, + const input &inp, const unique_ptr &turb, multiArray3d &mainDiagonal) { // suth -- method to get viscosity as a function of temperature (Sutherland's @@ -2215,6 +2279,7 @@ void procBlock::CalcViscFluxK(const sutherland &suth, const idealGas &eqnState, // implicit solver const auto viscCoeff = inp.ViscousCFLCoefficient(); + constexpr auto sixth = 1.0 / 6.0; // loop over all physical k-faces for (auto kp = 0, kg = numGhosts_; kg < fAreaK_.NumK() - numGhosts_; @@ -2239,17 +2304,36 @@ void procBlock::CalcViscFluxK(const sutherland &suth, const idealGas &eqnState, center_(ig, jg, kg), fCenterK_(ig, jg, kg)); + // Get wall distance at face + const auto mu = FaceReconCentral(viscosity_(ig, jg, kg - 1), + viscosity_(ig, jg, kg), + center_(ig, jg, kg - 1), + center_(ig, jg, kg), + fCenterK_(ig, jg, kg)); + // calculate viscous flux - vector3d tkeGrad, omegaGrad; - if (inp.IsTurbulent()) { - tkeGrad = grads.TkeGradK(ip, jp, kp); - omegaGrad = grads.OmegaGradK(ip, jp, kp); + tensor velGrad; + vector3d tempGrad, tkeGrad, omegaGrad; + CalcGradsK(ig, jg, kg, velGrad, tempGrad, tkeGrad, omegaGrad); + + // calculate turbulent eddy viscosity and blending coefficients + auto f1 = 0.0; + auto f2 = 0.0; + auto mut = 0.0; + if (isTurbulent_) { + turb->EddyViscAndBlending(state, velGrad, tkeGrad, omegaGrad, mu, + wDist, suth, mut, f1, f2); } - const viscousFlux tempViscFlux(grads.VelGradK(ip, jp, kp), suth, - eqnState, - grads.TempGradK(ip, jp, kp), + + // calculate viscous flux + const viscousFlux tempViscFlux(velGrad, suth, eqnState, tempGrad, this->FAreaUnitK(ig, jg, kg), - tkeGrad, omegaGrad, turb, state, wDist); + tkeGrad, omegaGrad, turb, state, mu, + mut, f1); + + // calculate projected center to center distance + const auto c2cDist = this->ProjC2CDist(ig, jg, kg, "k"); + // area vector points from left to right, so add to left cell, subtract // from right cell but viscous fluxes are subtracted from inviscid @@ -2259,6 +2343,27 @@ void procBlock::CalcViscFluxK(const sutherland &suth, const idealGas &eqnState, this->SubtractFromResidual(tempViscFlux * this->FAreaMagK(ig, jg, kg), ip, jp, kp - 1); + + // store gradients + velocityGrad_(ip, jp, kp - 1) += sixth * velGrad; + temperatureGrad_(ip, jp, kp - 1) += sixth * tempGrad; + if (isTurbulent_) { + tkeGrad_(ip, jp, kp - 1) += sixth * tkeGrad; + omegaGrad_(ip, jp, kp - 1) += sixth * omegaGrad; + eddyViscosity_(ig, jg, kg - 1) += sixth * mut; + f1_(ig, jg, kg - 1) += sixth * f1; + f2_(ig, jg, kg - 1) += sixth * f2; + } + + // if using block matrix on main diagonal, accumulate flux jacobian + if (inp.IsBlockMatrix()) { + // using mu, mut, and f1 at face + fluxJacobian fluxJac; + fluxJac.ApproxTSLJacobian(state, mu, mut, f1, eqnState, suth, + this->FAreaK(ig, jg, kg), c2cDist, + turb, inp, true, velGrad); + mainDiagonal(ip, jp, kp - 1) -= fluxJac; + } } // at right boundary there is no right cell to add to if (kg < fAreaK_.NumK() - numGhosts_ - 1) { @@ -2266,28 +2371,43 @@ void procBlock::CalcViscFluxK(const sutherland &suth, const idealGas &eqnState, this->FAreaMagK(ig, jg, kg), ip, jp, kp); + // store gradients + velocityGrad_(ip, jp, kp) += sixth * velGrad; + temperatureGrad_(ip, jp, kp) += sixth * tempGrad; + if (isTurbulent_) { + tkeGrad_(ip, jp, kp) += sixth * tkeGrad; + omegaGrad_(ip, jp, kp) += sixth * omegaGrad; + eddyViscosity_(ig, jg, kg) += sixth * mut; + f1_(ig, jg, kg) += sixth * f1; + f2_(ig, jg, kg) += sixth * f2; + } + // calculate component of wave speed. This is done on a cell by cell // basis, so only at the upper faces const auto viscSpecRad = state_(ig, jg, kg).ViscCellSpectralRadius( fAreaK_(ig, jg, kg), fAreaK_(ig, jg, kg + 1), eqnState, suth, - vol_(ig, jg, kg), turb); + vol_(ig, jg, kg), viscosity_(ig, jg, kg), + mut, turb); - const auto turbViscSpecRad = inp.IsTurbulent() ? - turb->ViscSpecRad(state_(ig, jg, kg), fAreaK_(ig, jg, kg), - fAreaK_(ig, jg, kg + 1), eqnState, suth, - vol_(ig, jg, kg)) : 0.0; + const auto turbViscSpecRad = isTurbulent_ ? + turb->ViscCellSpecRad(state_(ig, jg, kg), fAreaK_(ig, jg, kg), + fAreaK_(ig, jg, kg + 1), + viscosity_(ig, jg, kg), + suth, vol_(ig, jg, kg), mut, f1) + : 0.0; const uncoupledScalar specRad(viscSpecRad, turbViscSpecRad); specRadius_(ip, jp, kp) += specRad * viscCoeff; - - // if using block matrix on main diagonal, calculate flux jacobian + // if using block matrix on main diagonal, accumulate flux jacobian if (inp.IsBlockMatrix()) { - // mainDiagonal(ip, jp, kp).AddViscousJacobian( - // state_(ig, jg, kg), fAreaK_(ig, jg, kg), - // fAreaK_(ig, jg, kg + 1), eqnState, suth, - // vol_(ig, jg, kg), turb, inp.IsTurbulent()); + // using mu, mut, and f1 at face + fluxJacobian fluxJac; + fluxJac.ApproxTSLJacobian(state, mu, mut, f1, eqnState, suth, + this->FAreaK(ig, jg, kg), c2cDist, + turb, inp, false, velGrad); + mainDiagonal(ip, jp, kp) += fluxJac; } else { // factor 2 because visc spectral radius is not halved (Blazek 6.53) mainDiagonal(ip, jp, kp) += fluxJacobian(2.0 * specRad); @@ -4194,82 +4314,55 @@ bool procBlock::AtEdge(const int &ii, const int &jj, const int &kk, return atEdge; } -/* Function to swap ghost cell geometry between two blocks at an interblock -boundary. Slices are removed from the physical cells (extending into ghost cells -at the edges) of one block and inserted into the ghost cells of its partner -block. The reverse is also true. The slices are taken in the coordinate system -orientation of their parent block. +/* This member function differs from AtEdge in that it returns true for any + line of edge cells. In the example below, AtEdge returns true only for 1, + whereas AtEdgeInclusive returns true for 0, 1, 2, & 3. + + | + ghost | physical + ___ ___|__________ + | 0 | 1 | + |___|___| ghost + | 2 | 3 | + |___|___| + +*/ +bool procBlock::AtEdgeInclusive(const int &ii, const int &jj, const int &kk, + const bool &includeGhost, string &dir) const { + // ii -- i index of location to test + // jj -- j index of location to test + // kk -- k index of location to test + // includeGhost -- flag to determine if inputs include ghost cells or not + // dir -- direction that edge runs in - Interior Cells Ghost Cells Ghost Cells Interior Cells - ________ ______|________ _________ _______________|_______ _________ -Ui-3/2 Ui-1/2 | Uj+1/2 Uj+3/2 Ui-3/2 Ui-1/2 | Uj+1/2 Uj+3/2 - | | | | | | | | | | - | Ui-1 | Ui | Uj | Uj+1 | | Ui-1 | Ui | Uj | Uj+1 | - | | | | | | | | | | - |________|______|________|_________| |________|______|_______|_________| - | | + auto atEdge = false; -The above diagram shows the resulting values after the ghost cell swap. The -logic ensures that the ghost cells at the interblock boundary exactly match -their partner block as if there were no separation in the grid. + const auto offset = includeGhost ? numGhosts_ : 0; -Only 3 faces at each ghost cell need to be swapped (i.e. the lower face for Ui -is the upper face for Ui-1). At the end of a line (i-line, j-line or k-line), -both the upper and lower faces need to be swapped. -*/ -void SwapGeomSlice(interblock &inter, procBlock &blk1, procBlock &blk2) { - // inter -- interblock boundary information - // blk1 -- first block involved in interblock boundary - // blk2 -- second block involved in interblock boundary - - // Get indices for slice coming from first block to swap - auto is1 = 0; - auto ie1 = 0; - auto js1 = 0; - auto je1 = 0; - auto ks1 = 0; - auto ke1 = 0; - - inter.FirstSliceIndices(is1, ie1, js1, je1, ks1, ke1, blk1.NumGhosts()); - - // Get indices for slice coming from second block to swap - auto is2 = 0; - auto ie2 = 0; - auto js2 = 0; - auto je2 = 0; - auto ks2 = 0; - auto ke2 = 0; - - inter.SecondSliceIndices(is2, ie2, js2, je2, ks2, ke2, blk2.NumGhosts()); - - const auto geom1 = geomSlice(blk1, is1, ie1, js1, je1, ks1, ke1); - const auto geom2 = geomSlice(blk2, is2, ie2, js2, je2, ks2, ke2); - - // change interblocks to work with slice and ghosts - interblock inter1 = inter; - interblock inter2 = inter; - inter1.AdjustForSlice(false, blk1.NumGhosts()); - inter2.AdjustForSlice(true, blk2.NumGhosts()); - - // put slices in proper blocks - // return vector determining if any of the 4 edges of the interblock need to - // be updated for a "t" intersection - const auto adjEdge1 = blk1.PutGeomSlice(geom2, inter2, blk2.NumGhosts(), - blk2.NumGhosts()); - const auto adjEdge2 = blk2.PutGeomSlice(geom1, inter1, blk1.NumGhosts(), - blk1.NumGhosts()); - - // if an interblock border needs to be updated, update - for (auto ii = 0; ii < static_cast(adjEdge1.size()); ii++) { - if (adjEdge1[ii]) { - inter.UpdateBorderFirst(ii); - } - if (adjEdge2[ii]) { - inter.UpdateBorderSecond(ii); - } + // at i-edge - i in physical cell range, j/k in ghost cells + if ((ii >= offset && ii < this->NumI() + offset) && + (jj < offset || jj >= this->NumJ() + offset) && + (kk < offset || kk >= this->NumK() + offset)) { + atEdge = true; + dir = "i"; + // at j-edge - j in physical cell range, i/k in ghost cells + } else if ((ii < offset || ii >= this->NumI() + offset) && + (jj >= offset && jj < this->NumJ() + offset) && + (kk < offset || kk >= this->NumK() + offset)) { + atEdge = true; + dir = "j"; + // at k-edge - k in physical cell range, i/j in ghost cells + } else if ((ii < offset || ii >= this->NumI() + offset) && + (jj < offset || jj >= this->NumJ() + offset) && + (kk >= offset && kk < this->NumK() + offset)) { + atEdge = true; + dir = "k"; } + + return atEdge; } + /* Function to swap ghost cells between two blocks at an interblock boundary. Slices are removed from the physical cells (extending into ghost cells at the edges) of one block and inserted into the ghost cells of its partner @@ -4296,6 +4389,16 @@ void procBlock::SwapStateSlice(const interblock &inter, procBlock &blk) { state_.SwapSlice(inter, blk.state_, numGhosts_, blk.NumGhosts()); } +void procBlock::SwapTurbSlice(const interblock &inter, procBlock &blk) { + // inter -- interblock boundary information + // blk -- second block involved in interblock boundary + + eddyViscosity_.SwapSlice(inter, blk.eddyViscosity_, numGhosts_, + blk.NumGhosts()); + f1_.SwapSlice(inter, blk.f1_, numGhosts_, blk.NumGhosts()); + f2_.SwapSlice(inter, blk.f2_, numGhosts_, blk.NumGhosts()); +} + /* Function to swap slice using MPI. This is similar to the SwapSlice function, but is called when the neighboring procBlocks are on different @@ -4310,59 +4413,16 @@ void procBlock::SwapStateSliceMPI(const interblock &inter, const int &rank, state_.SwapSliceMPI(inter, rank, MPI_cellData, numGhosts_); } -/* Function to populate ghost cells with proper cell states for inviscid flow -calculation. This function operates on the entire grid and uses interblock -boundaries to pass the correct data between grid blocks. -*/ -void GetBoundaryConditions(vector &states, const input &inp, - const idealGas &eos, const sutherland &suth, - const unique_ptr &turb, - vector &connections, const int &rank, - const MPI_Datatype &MPI_cellData) { - // states -- vector of all procBlocks in the solution domain - // inp -- all input variables - // eos -- equation of state - // suth -- sutherland's law for viscosity - // connections -- vector of interblock connections +void procBlock::SwapTurbSliceMPI(const interblock &inter, const int &rank) { + // inter -- interblock boundary information // rank -- processor rank - // MPI_cellData -- data type to pass primVars, genArray - - // loop over all blocks and assign inviscid ghost cells - for (auto ii = 0; ii < static_cast(states.size()); ii++) { - states[ii].AssignInviscidGhostCells(inp, eos, suth, turb); - } - - // loop over connections and swap ghost cells where needed - for (auto ii = 0; ii < static_cast(connections.size()); ii++) { - if (connections[ii].RankFirst() == rank && - connections[ii].RankSecond() == rank) { // both sides of interblock - // are on this processor, swap - // w/o mpi - states[connections[ii].LocalBlockFirst()] - .SwapStateSlice(connections[ii], - states[connections[ii].LocalBlockSecond()]); - } else if (connections[ii].RankFirst() == - rank) { // rank matches rank of first side of interblock, - // swap over mpi - states[connections[ii].LocalBlockFirst()] - .SwapStateSliceMPI(connections[ii], rank, MPI_cellData); - - } else if (connections[ii].RankSecond() == - rank) { // rank matches rank of second side of interblock, - // swap over mpi - states[connections[ii].LocalBlockSecond()] - .SwapStateSliceMPI(connections[ii], rank, MPI_cellData); - } - // if rank doesn't match either side of interblock, then do nothing and - // move on to the next interblock - } - // loop over all blocks and get ghost cell edge data - for (auto ii = 0; ii < static_cast(states.size()); ii++) { - states[ii].AssignInviscidGhostCellsEdge(inp, eos, suth, turb); - } + eddyViscosity_.SwapSliceMPI(inter, rank, MPI_DOUBLE, numGhosts_, 1); + f1_.SwapSliceMPI(inter, rank, MPI_DOUBLE, numGhosts_, 2); + f2_.SwapSliceMPI(inter, rank, MPI_DOUBLE, numGhosts_, 3); } + /* Member function to overwrite a section of a procBlock's geometry with a geomSlice. The function uses the orientation supplied in the interblock to orient the geomSlice relative to the procBlock. It assumes that the procBlock @@ -4423,7 +4483,7 @@ vector procBlock::PutGeomSlice(const geomSlice &slice, interblock &inter, << inter.Dir2EndFirst() - inter.Dir2StartFirst() << ", " << d3 << endl; cerr << "Direction I, J, K of geomSlice: " << slice.NumI() << ", " << slice.NumJ() << ", " << slice.NumK() << endl; - exit(1); + exit(EXIT_FAILURE); } // adjust insertion indices if patch borders another interblock on the same @@ -4494,7 +4554,7 @@ vector procBlock::PutGeomSlice(const geomSlice &slice, interblock &inter, cerr << "ERROR: Error in procBlock::PutGeomSlice(). Ghost cell " "edge direction does not match interblock direction 1 or " "2." << endl; - exit(1); + exit(EXIT_FAILURE); } } @@ -5207,7 +5267,7 @@ vector procBlock::PutGeomSlice(const geomSlice &slice, interblock &inter, "face quantities because behavior for interface with " "boundary pair " << inter.BoundaryFirst() << ", " << inter.BoundarySecond() << " is not defined." << endl; - exit(1); + exit(EXIT_FAILURE); } } } @@ -5250,6 +5310,9 @@ void procBlock::PackSendGeomMPI(const MPI_Datatype &MPI_cellData, MPI_Pack_size(8, MPI_INT, MPI_COMM_WORLD, &tempSize); // add size for ints in class procBlock sendBufSize += tempSize; + MPI_Pack_size(2, MPI_CXX_BOOL, MPI_COMM_WORLD, + &tempSize); // add size for bools in class procBlock + sendBufSize += tempSize; MPI_Pack_size(state_.Size(), MPI_cellData, MPI_COMM_WORLD, &tempSize); // add size for states sendBufSize += tempSize; @@ -5320,6 +5383,10 @@ void procBlock::PackSendGeomMPI(const MPI_Datatype &MPI_cellData, MPI_COMM_WORLD); MPI_Pack(&globalPos_, 1, MPI_INT, sendBuffer, sendBufSize, &position, MPI_COMM_WORLD); + MPI_Pack(&isViscous_, 1, MPI_CXX_BOOL, sendBuffer, sendBufSize, &position, + MPI_COMM_WORLD); + MPI_Pack(&isTurbulent_, 1, MPI_CXX_BOOL, sendBuffer, sendBufSize, &position, + MPI_COMM_WORLD); MPI_Pack(&state_(0, 0, 0), state_.Size(), MPI_cellData, sendBuffer, sendBufSize, &position, MPI_COMM_WORLD); MPI_Pack(¢er_(0, 0, 0), center_.Size(), MPI_vec3d, sendBuffer, @@ -5391,6 +5458,12 @@ void procBlock::RecvUnpackGeomMPI(const MPI_Datatype &MPI_cellData, MPI_Unpack(recvBuffer, recvBufSize, &position, &globalPos_, 1, MPI_INT, MPI_COMM_WORLD); + // unpack procBlock bools + MPI_Unpack(recvBuffer, recvBufSize, &position, &isViscous_, 1, + MPI_CXX_BOOL, MPI_COMM_WORLD); + MPI_Unpack(recvBuffer, recvBufSize, &position, &isTurbulent_, 1, + MPI_CXX_BOOL, MPI_COMM_WORLD); + // clean and resize the vectors in the class to this->CleanResizeVecs(numI, numJ, numK); @@ -5460,14 +5533,34 @@ void procBlock::CleanResizeVecs(const int &numI, const int &numJ, residual_.ClearResize(numI, numJ, numK); specRadius_.ClearResize(numI, numJ, numK); dt_.ClearResize(numI, numJ, numK); + + temperature_.ClearResize(ig, jg, kg); + + if (isViscous_) { + velocityGrad_.ClearResize(numI, numJ, numK); + temperatureGrad_.ClearResize(numI, numJ, numK); + viscosity_.ClearResize(ig, jg, kg); + } + + if (isTurbulent_) { + tkeGrad_.ClearResize(numI, numJ, numK); + omegaGrad_.ClearResize(numI, numJ, numK); + eddyViscosity_.ClearResize(ig, jg, kg); + f1_.ClearResize(ig, jg, kg); + f2_.ClearResize(ig, jg, kg); + } } /*Member function to receive and unpack procBlock state data. This is used to * gather the solution on the ROOT processor to write out the solution. */ void procBlock::RecvUnpackSolMPI(const MPI_Datatype &MPI_cellData, - const MPI_Datatype &MPI_uncoupledScalar) { + const MPI_Datatype &MPI_uncoupledScalar, + const MPI_Datatype &MPI_vec3d, + const MPI_Datatype &MPI_tensorDouble) { // MPI_cellData -- MPI data type for cell data // MPI_uncoupledScalar -- MPI data type for uncoupledScalar + // MPI_vec3d -- MPI data type for vector3d + // MPI_tensorDouble -- MPI data taype for tensor MPI_Status status; // allocate MPI_Status structure @@ -5503,6 +5596,39 @@ void procBlock::RecvUnpackSolMPI(const MPI_Datatype &MPI_cellData, MPI_Unpack(recvBuffer, recvBufSize, &position, &specRadius_(0, 0, 0), specRadius_.Size(), MPI_uncoupledScalar, MPI_COMM_WORLD); // unpack average wave speeds + MPI_Unpack(recvBuffer, recvBufSize, &position, &temperature_(0, 0, 0), + temperature_.Size(), MPI_DOUBLE, + MPI_COMM_WORLD); // unpack temperature + + if (isViscous_) { + MPI_Unpack(recvBuffer, recvBufSize, &position, &viscosity_(0, 0, 0), + viscosity_.Size(), MPI_DOUBLE, + MPI_COMM_WORLD); // unpack viscosity + MPI_Unpack(recvBuffer, recvBufSize, &position, &velocityGrad_(0, 0, 0), + velocityGrad_.Size(), MPI_tensorDouble, + MPI_COMM_WORLD); // unpack velocity gradient + MPI_Unpack(recvBuffer, recvBufSize, &position, &temperatureGrad_(0, 0, 0), + temperatureGrad_.Size(), MPI_vec3d, + MPI_COMM_WORLD); // unpack temperature gradient + } + + if (isTurbulent_) { + MPI_Unpack(recvBuffer, recvBufSize, &position, &eddyViscosity_(0, 0, 0), + eddyViscosity_.Size(), MPI_DOUBLE, + MPI_COMM_WORLD); // unpack eddy viscosity + MPI_Unpack(recvBuffer, recvBufSize, &position, &f1_(0, 0, 0), + f1_.Size(), MPI_DOUBLE, + MPI_COMM_WORLD); // unpack blending variable f1 + MPI_Unpack(recvBuffer, recvBufSize, &position, &f2_(0, 0, 0), + f2_.Size(), MPI_DOUBLE, + MPI_COMM_WORLD); // unpack blending variable f2 + MPI_Unpack(recvBuffer, recvBufSize, &position, &tkeGrad_(0, 0, 0), + tkeGrad_.Size(), MPI_vec3d, + MPI_COMM_WORLD); // unpack tke gradient + MPI_Unpack(recvBuffer, recvBufSize, &position, &omegaGrad_(0, 0, 0), + omegaGrad_.Size(), MPI_vec3d, + MPI_COMM_WORLD); // unpack omega gradient + } delete[] recvBuffer; // deallocate receiving buffer } @@ -5511,9 +5637,13 @@ void procBlock::RecvUnpackSolMPI(const MPI_Datatype &MPI_cellData, * This is used to gather the solution on the ROOT processor to write out the * solution. */ void procBlock::PackSendSolMPI(const MPI_Datatype &MPI_cellData, - const MPI_Datatype &MPI_uncoupledScalar) const { + const MPI_Datatype &MPI_uncoupledScalar, + const MPI_Datatype &MPI_vec3d, + const MPI_Datatype &MPI_tensorDouble) const { // MPI_cellData -- MPI data type for cell data // MPI_uncoupledScalar -- MPI data type for uncoupledScalar + // MPI_vec3d -- MPI data type for vector3d + // MPI_tensorDouble -- MPI data taype for tensor // determine size of buffer to send auto sendBufSize = 0; @@ -5533,6 +5663,40 @@ void procBlock::PackSendSolMPI(const MPI_Datatype &MPI_cellData, MPI_Pack_size(specRadius_.Size(), MPI_uncoupledScalar, MPI_COMM_WORLD, &tempSize); // add size for average wave speed sendBufSize += tempSize; + MPI_Pack_size(temperature_.Size(), MPI_DOUBLE, MPI_COMM_WORLD, + &tempSize); // add size for temperature + sendBufSize += tempSize; + + if (isViscous_) { + MPI_Pack_size(viscosity_.Size(), MPI_DOUBLE, MPI_COMM_WORLD, + &tempSize); // add size for viscosity + sendBufSize += tempSize; + MPI_Pack_size(velocityGrad_.Size(), MPI_tensorDouble, MPI_COMM_WORLD, + &tempSize); // add size for velocity gradient + sendBufSize += tempSize; + MPI_Pack_size(temperatureGrad_.Size(), MPI_vec3d, MPI_COMM_WORLD, + &tempSize); // add size for temperature gradient + sendBufSize += tempSize; + } + + if (isTurbulent_) { + MPI_Pack_size(eddyViscosity_.Size(), MPI_DOUBLE, MPI_COMM_WORLD, + &tempSize); // add size for eddy viscosity + sendBufSize += tempSize; + MPI_Pack_size(f1_.Size(), MPI_DOUBLE, MPI_COMM_WORLD, + &tempSize); // add size for blending variable f1 + sendBufSize += tempSize; + MPI_Pack_size(f2_.Size(), MPI_DOUBLE, MPI_COMM_WORLD, + &tempSize); // add size for blending variable f2 + sendBufSize += tempSize; + MPI_Pack_size(tkeGrad_.Size(), MPI_vec3d, MPI_COMM_WORLD, + &tempSize); // add size for tke gradient + sendBufSize += tempSize; + MPI_Pack_size(omegaGrad_.Size(), MPI_vec3d, MPI_COMM_WORLD, + &tempSize); // add size for omega gradient + sendBufSize += tempSize; + } + auto *sendBuffer = new char[sendBufSize]; // allocate buffer to pack data // into @@ -5549,6 +5713,30 @@ void procBlock::PackSendSolMPI(const MPI_Datatype &MPI_cellData, sendBuffer, sendBufSize, &position, MPI_COMM_WORLD); MPI_Pack(&specRadius_(0, 0, 0), specRadius_.Size(), MPI_uncoupledScalar, sendBuffer, sendBufSize, &position, MPI_COMM_WORLD); + MPI_Pack(&temperature_(0, 0, 0), temperature_.Size(), MPI_DOUBLE, + sendBuffer, sendBufSize, &position, MPI_COMM_WORLD); + + if (isViscous_) { + MPI_Pack(&viscosity_(0, 0, 0), viscosity_.Size(), MPI_DOUBLE, + sendBuffer, sendBufSize, &position, MPI_COMM_WORLD); + MPI_Pack(&velocityGrad_(0, 0, 0), velocityGrad_.Size(), MPI_tensorDouble, + sendBuffer, sendBufSize, &position, MPI_COMM_WORLD); + MPI_Pack(&temperatureGrad_(0, 0, 0), temperatureGrad_.Size(), MPI_vec3d, + sendBuffer, sendBufSize, &position, MPI_COMM_WORLD); + } + + if (isTurbulent_) { + MPI_Pack(&eddyViscosity_(0, 0, 0), eddyViscosity_.Size(), MPI_DOUBLE, + sendBuffer, sendBufSize, &position, MPI_COMM_WORLD); + MPI_Pack(&f1_(0, 0, 0), f1_.Size(), MPI_DOUBLE, + sendBuffer, sendBufSize, &position, MPI_COMM_WORLD); + MPI_Pack(&f2_(0, 0, 0), f2_.Size(), MPI_DOUBLE, + sendBuffer, sendBufSize, &position, MPI_COMM_WORLD); + MPI_Pack(&tkeGrad_(0, 0, 0), tkeGrad_.Size(), MPI_vec3d, + sendBuffer, sendBufSize, &position, MPI_COMM_WORLD); + MPI_Pack(&omegaGrad_(0, 0, 0), omegaGrad_.Size(), MPI_vec3d, + sendBuffer, sendBufSize, &position, MPI_COMM_WORLD); + } // send buffer to appropriate processor MPI_Send(sendBuffer, sendBufSize, MPI_PACKED, ROOTP, globalPos_, @@ -5576,8 +5764,10 @@ procBlock procBlock::Split(const string &dir, const int &ind, const int &num, const auto numI2 = this->NumI() - ind; const auto numI1 = this->NumI() - numI2; - procBlock blk1(numI1, this->NumJ(), this->NumK(), numGhosts_); - procBlock blk2(numI2, this->NumJ(), this->NumK(), numGhosts_); + procBlock blk1(numI1, this->NumJ(), this->NumK(), numGhosts_, isViscous_, + isTurbulent_); + procBlock blk2(numI2, this->NumJ(), this->NumK(), numGhosts_, isViscous_, + isTurbulent_); blk1.parBlock_ = parBlock_; blk2.parBlock_ = parBlock_; @@ -5612,6 +5802,21 @@ procBlock procBlock::Split(const string &dir, const int &ind, const int &num, center_.Slice(0, iMaxG1, 0, jMaxG, 0, kMaxG)); blk1.wallDist_.Insert(0, iMaxG1, 0, jMaxG, 0, kMaxG, wallDist_.Slice(0, iMaxG1, 0, jMaxG, 0, kMaxG)); + blk1.temperature_.Insert(0, iMaxG1, 0, jMaxG, 0, kMaxG, + temperature_.Slice(0, iMaxG1, 0, jMaxG, 0, kMaxG)); + if (isViscous_) { + blk1.viscosity_.Insert(0, iMaxG1, 0, jMaxG, 0, kMaxG, + viscosity_.Slice(0, iMaxG1, 0, jMaxG, 0, kMaxG)); + } + if (isTurbulent_) { + blk1.eddyViscosity_.Insert(0, iMaxG1, 0, jMaxG, 0, kMaxG, + eddyViscosity_.Slice(0, iMaxG1, 0, jMaxG, + 0, kMaxG)); + blk1.f1_.Insert(0, iMaxG1, 0, jMaxG, 0, kMaxG, + f1_.Slice(0, iMaxG1, 0, jMaxG, 0, kMaxG)); + blk1.f2_.Insert(0, iMaxG1, 0, jMaxG, 0, kMaxG, + f2_.Slice(0, iMaxG1, 0, jMaxG, 0, kMaxG)); + } // assign cell variables without ghost cells blk1.specRadius_.Insert(0, iMax1, 0, jMax, 0, kMax, @@ -5620,6 +5825,20 @@ procBlock procBlock::Split(const string &dir, const int &ind, const int &num, dt_.Slice(0, iMax1, 0, jMax, 0, kMax)); blk1.residual_.Insert(0, iMax1, 0, jMax, 0, kMax, residual_.Slice(0, iMax1, 0, jMax, 0, kMax)); + if (isViscous_) { + blk1.velocityGrad_.Insert(0, iMax1, 0, jMax, 0, kMax, + velocityGrad_.Slice(0, iMax1, 0, jMax, 0, + kMax)); + blk1.temperatureGrad_.Insert(0, iMax1, 0, jMax, 0, kMax, + temperatureGrad_.Slice(0, iMax1, 0, jMax, 0, + kMax)); + } + if (isTurbulent_) { + blk1.tkeGrad_.Insert(0, iMax1, 0, jMax, 0, kMax, + tkeGrad_.Slice(0, iMax1, 0, jMax, 0, kMax)); + blk1.omegaGrad_.Insert(0, iMax1, 0, jMax, 0, kMax, + omegaGrad_.Slice(0, iMax1, 0, jMax, 0, kMax)); + } // assign face variables blk1.fAreaI_.Insert(0, iMaxG1 + 1, 0, jMaxG, 0, kMaxG, @@ -5648,6 +5867,23 @@ procBlock procBlock::Split(const string &dir, const int &ind, const int &num, blk2.wallDist_.Insert(0, iMaxG2, 0, jMaxG, 0, kMaxG, wallDist_.Slice(iMinPG2, iMaxPG2, 0, jMaxG, 0, kMaxG)); + blk2.temperature_.Insert(0, iMaxG2, 0, jMaxG, 0, kMaxG, + temperature_.Slice(iMinPG2, iMaxPG2, 0, jMaxG, 0, + kMaxG)); + if (isViscous_) { + blk2.viscosity_.Insert(0, iMaxG2, 0, jMaxG, 0, kMaxG, + viscosity_.Slice(iMinPG2, iMaxPG2, 0, jMaxG, 0, + kMaxG)); + } + if (isTurbulent_) { + blk2.eddyViscosity_.Insert(0, iMaxG2, 0, jMaxG, 0, kMaxG, + eddyViscosity_.Slice(iMinPG2, iMaxPG2, 0, + jMaxG, 0, kMaxG)); + blk2.f1_.Insert(0, iMaxG2, 0, jMaxG, 0, kMaxG, + f1_.Slice(iMinPG2, iMaxPG2, 0, jMaxG, 0, kMaxG)); + blk2.f2_.Insert(0, iMaxG2, 0, jMaxG, 0, kMaxG, + f2_.Slice(iMinPG2, iMaxPG2, 0, jMaxG, 0, kMaxG)); + } // assign cell variables without ghost cells blk2.specRadius_.Insert(0, iMax2, 0, jMax, 0, kMax, @@ -5657,6 +5893,22 @@ procBlock procBlock::Split(const string &dir, const int &ind, const int &num, dt_.Slice(iMinP2, iMaxP2, 0, jMax, 0, kMax)); blk2.residual_.Insert(0, iMax2, 0, jMax, 0, kMax, residual_.Slice(iMinP2, iMaxP2, 0, jMax, 0, kMax)); + if (isViscous_) { + blk2.velocityGrad_.Insert(0, iMax2, 0, jMax, 0, kMax, + velocityGrad_.Slice(iMinP2, iMaxP2, 0, jMax, 0, + kMax)); + blk2.temperatureGrad_.Insert(0, iMax2, 0, jMax, 0, kMax, + temperatureGrad_.Slice(iMinP2, iMaxP2, 0, + jMax, 0, kMax)); + } + if (isTurbulent_) { + blk2.tkeGrad_.Insert(0, iMax2, 0, jMax, 0, kMax, + tkeGrad_.Slice(iMinP2, iMaxP2, 0, jMax, 0, kMax)); + blk2.omegaGrad_.Insert(0, iMax2, 0, jMax, 0, kMax, + omegaGrad_.Slice(iMinP2, iMaxP2, 0, jMax, 0, + kMax)); + } + // assign face variables blk2.fAreaI_.Insert(0, iMaxG2 + 1, 0, jMaxG, 0, kMaxG, fAreaI_.Slice(iMinPG2, iMaxPG2 + 1, 0, jMaxG, 0, @@ -5688,8 +5940,10 @@ procBlock procBlock::Split(const string &dir, const int &ind, const int &num, const auto numJ2 = this->NumJ() - ind; const auto numJ1 = this->NumJ() - numJ2; - procBlock blk1(this->NumI(), numJ1, this->NumK(), numGhosts_); - procBlock blk2(this->NumI(), numJ2, this->NumK(), numGhosts_); + procBlock blk1(this->NumI(), numJ1, this->NumK(), numGhosts_, isViscous_, + isTurbulent_); + procBlock blk2(this->NumI(), numJ2, this->NumK(), numGhosts_, isViscous_, + isTurbulent_); blk1.parBlock_ = parBlock_; blk2.parBlock_ = parBlock_; @@ -5724,6 +5978,21 @@ procBlock procBlock::Split(const string &dir, const int &ind, const int &num, center_.Slice(0, iMaxG, 0, jMaxG1, 0, kMaxG)); blk1.wallDist_.Insert(0, iMaxG, 0, jMaxG1, 0, kMaxG, wallDist_.Slice(0, iMaxG, 0, jMaxG1, 0, kMaxG)); + blk1.temperature_.Insert(0, iMaxG, 0, jMaxG1, 0, kMaxG, + temperature_.Slice(0, iMaxG, 0, jMaxG1, 0, kMaxG)); + if (isViscous_) { + blk1.viscosity_.Insert(0, iMaxG, 0, jMaxG1, 0, kMaxG, + viscosity_.Slice(0, iMaxG, 0, jMaxG1, 0, kMaxG)); + } + if (isTurbulent_) { + blk1.eddyViscosity_.Insert(0, iMaxG, 0, jMaxG1, 0, kMaxG, + eddyViscosity_.Slice(0, iMaxG, 0, jMaxG1, 0, + kMaxG)); + blk1.f1_.Insert(0, iMaxG, 0, jMaxG1, 0, kMaxG, + f1_.Slice(0, iMaxG, 0, jMaxG1, 0, kMaxG)); + blk1.f2_.Insert(0, iMaxG, 0, jMaxG1, 0, kMaxG, + f2_.Slice(0, iMaxG, 0, jMaxG1, 0, kMaxG)); + } // assign cell variables without ghost cells blk1.specRadius_.Insert(0, iMax, 0, jMax1, 0, kMax, @@ -5732,6 +6001,20 @@ procBlock procBlock::Split(const string &dir, const int &ind, const int &num, dt_.Slice(0, iMax, 0, jMax1, 0, kMax)); blk1.residual_.Insert(0, iMax, 0, jMax1, 0, kMax, residual_.Slice(0, iMax, 0, jMax1, 0, kMax)); + if (isViscous_) { + blk1.velocityGrad_.Insert(0, iMax, 0, jMax1, 0, kMax, + velocityGrad_.Slice(0, iMax, 0, jMax1, 0, + kMax)); + blk1.temperatureGrad_.Insert(0, iMax, 0, jMax1, 0, kMax, + temperatureGrad_.Slice(0, iMax, 0, jMax1, + 0, kMax)); + } + if (isTurbulent_) { + blk1.tkeGrad_.Insert(0, iMax, 0, jMax1, 0, kMax, + tkeGrad_.Slice(0, iMax, 0, jMax1, 0, kMax)); + blk1.omegaGrad_.Insert(0, iMax, 0, jMax1, 0, kMax, + omegaGrad_.Slice(0, iMax, 0, jMax1, 0, kMax)); + } // assign face variables blk1.fAreaI_.Insert(0, iMaxG + 1, 0, jMaxG1, 0, kMaxG, @@ -5760,6 +6043,23 @@ procBlock procBlock::Split(const string &dir, const int &ind, const int &num, blk2.wallDist_.Insert(0, iMaxG, 0, jMaxG2, 0, kMaxG, wallDist_.Slice(0, iMaxG, jMinPG2, jMaxPG2, 0, kMaxG)); + blk2.temperature_.Insert(0, iMaxG, 0, jMaxG2, 0, kMaxG, + temperature_.Slice(0, iMaxG, jMinPG2, jMaxPG2, 0, + kMaxG)); + if (isViscous_) { + blk2.viscosity_.Insert(0, iMaxG, 0, jMaxG2, 0, kMaxG, + viscosity_.Slice(0, iMaxG, jMinPG2, jMaxPG2, 0, + kMaxG)); + } + if (isTurbulent_) { + blk2.eddyViscosity_.Insert(0, iMaxG, 0, jMaxG2, 0, kMaxG, + eddyViscosity_.Slice(0, iMaxG, jMinPG2, + jMaxPG2, 0, kMaxG)); + blk2.f1_.Insert(0, iMaxG, 0, jMaxG2, 0, kMaxG, + f1_.Slice(0, iMaxG, jMinPG2, jMaxPG2, 0, kMaxG)); + blk2.f2_.Insert(0, iMaxG, 0, jMaxG2, 0, kMaxG, + f2_.Slice(0, iMaxG, jMinPG2, jMaxPG2, 0, kMaxG)); + } // assign cell variables without ghost cells blk2.specRadius_.Insert(0, iMax, 0, jMax2, 0, kMax, @@ -5769,6 +6069,22 @@ procBlock procBlock::Split(const string &dir, const int &ind, const int &num, dt_.Slice(0, iMax, jMinP2, jMaxP2, 0, kMax)); blk2.residual_.Insert(0, iMax, 0, jMax2, 0, kMax, residual_.Slice(0, iMax, jMinP2, jMaxP2, 0, kMax)); + if (isViscous_) { + blk2.velocityGrad_.Insert(0, iMax, 0, jMax2, 0, kMax, + velocityGrad_.Slice(0, iMax, jMinP2, jMaxP2, 0, + kMax)); + blk2.temperatureGrad_.Insert(0, iMax, 0, jMax2, 0, kMax, + temperatureGrad_.Slice(0, iMax, jMinP2, + jMaxP2, 0, kMax)); + } + if (isTurbulent_) { + blk2.tkeGrad_.Insert(0, iMax, 0, jMax2, 0, kMax, + tkeGrad_.Slice(0, iMax, jMinP2, jMaxP2, 0, kMax)); + blk2.omegaGrad_.Insert(0, iMax, 0, jMax2, 0, kMax, + omegaGrad_.Slice(0, iMax, jMinP2, jMaxP2, 0, + kMax)); + } + // assign face variables blk2.fAreaI_.Insert(0, iMaxG + 1, 0, jMaxG2, 0, kMaxG, fAreaI_.Slice(0, iMaxG + 1, jMinPG2, jMaxPG2, 0, @@ -5800,8 +6116,10 @@ procBlock procBlock::Split(const string &dir, const int &ind, const int &num, const auto numK2 = this->NumK() - ind; const auto numK1 = this->NumK() - numK2; - procBlock blk1(this->NumI(), this->NumJ(), numK1, numGhosts_); - procBlock blk2(this->NumI(), this->NumJ(), numK2, numGhosts_); + procBlock blk1(this->NumI(), this->NumJ(), numK1, numGhosts_, isViscous_, + isTurbulent_); + procBlock blk2(this->NumI(), this->NumJ(), numK2, numGhosts_, isViscous_, + isTurbulent_); blk1.parBlock_ = parBlock_; blk2.parBlock_ = parBlock_; @@ -5836,6 +6154,21 @@ procBlock procBlock::Split(const string &dir, const int &ind, const int &num, center_.Slice(0, iMaxG, 0, jMaxG, 0, kMaxG1)); blk1.wallDist_.Insert(0, iMaxG, 0, jMaxG, 0, kMaxG1, wallDist_.Slice(0, iMaxG, 0, jMaxG, 0, kMaxG1)); + blk1.temperature_.Insert(0, iMaxG, 0, jMaxG, 0, kMaxG1, + temperature_.Slice(0, iMaxG, 0, jMaxG, 0, kMaxG1)); + if (isViscous_) { + blk1.viscosity_.Insert(0, iMaxG, 0, jMaxG, 0, kMaxG1, + viscosity_.Slice(0, iMaxG, 0, jMaxG, 0, kMaxG1)); + } + if (isTurbulent_) { + blk1.eddyViscosity_.Insert(0, iMaxG, 0, jMaxG, 0, kMaxG1, + eddyViscosity_.Slice(0, iMaxG, 0, jMaxG, 0, + kMaxG1)); + blk1.f1_.Insert(0, iMaxG, 0, jMaxG, 0, kMaxG1, + f1_.Slice(0, iMaxG, 0, jMaxG, 0, kMaxG1)); + blk1.f2_.Insert(0, iMaxG, 0, jMaxG, 0, kMaxG1, + f2_.Slice(0, iMaxG, 0, jMaxG, 0, kMaxG1)); + } // assign cell variables without ghost cells blk1.specRadius_.Insert(0, iMax, 0, jMax, 0, kMax1, @@ -5844,6 +6177,20 @@ procBlock procBlock::Split(const string &dir, const int &ind, const int &num, dt_.Slice(0, iMax, 0, jMax, 0, kMax1)); blk1.residual_.Insert(0, iMax, 0, jMax, 0, kMax1, residual_.Slice(0, iMax, 0, jMax, 0, kMax1)); + if (isViscous_) { + blk1.velocityGrad_.Insert(0, iMax, 0, jMax, 0, kMax1, + velocityGrad_.Slice(0, iMax, 0, jMax, 0, + kMax1)); + blk1.temperatureGrad_.Insert(0, iMax, 0, jMax, 0, kMax1, + temperatureGrad_.Slice(0, iMax, 0, jMax, + 0, kMax1)); + } + if (isTurbulent_) { + blk1.tkeGrad_.Insert(0, iMax, 0, jMax, 0, kMax1, + tkeGrad_.Slice(0, iMax, 0, jMax, 0, kMax1)); + blk1.omegaGrad_.Insert(0, iMax, 0, jMax, 0, kMax1, + omegaGrad_.Slice(0, iMax, 0, jMax, 0, kMax1)); + } // assign face variables blk1.fAreaI_.Insert(0, iMaxG + 1, 0, jMaxG, 0, kMaxG1, @@ -5872,6 +6219,23 @@ procBlock procBlock::Split(const string &dir, const int &ind, const int &num, blk2.wallDist_.Insert(0, iMaxG, 0, jMaxG, 0, kMaxG2, wallDist_.Slice(0, iMaxG, 0, jMaxG, kMinPG2, kMaxPG2)); + blk2.temperature_.Insert(0, iMaxG, 0, jMaxG, 0, kMaxG2, + temperature_.Slice(0, iMaxG, 0, jMaxG, kMinPG2, + kMaxPG2)); + if (isViscous_) { + blk2.viscosity_.Insert(0, iMaxG, 0, jMaxG, 0, kMaxG2, + viscosity_.Slice(0, iMaxG, 0, jMaxG, kMinPG2, + kMaxPG2)); + } + if (isTurbulent_) { + blk2.eddyViscosity_.Insert(0, iMaxG, 0, jMaxG, 0, kMaxG2, + eddyViscosity_.Slice(0, iMaxG, 0, jMaxG, + kMinPG2, kMaxPG2)); + blk2.f1_.Insert(0, iMaxG, 0, jMaxG, 0, kMaxG2, + f1_.Slice(0, iMaxG, 0, jMaxG, kMinPG2, kMaxPG2)); + blk2.f2_.Insert(0, iMaxG, 0, jMaxG, 0, kMaxG2, + f2_.Slice(0, iMaxG, 0, jMaxG, kMinPG2, kMaxPG2)); + } // assign cell variables without ghost cells blk2.specRadius_.Insert(0, iMax, 0, jMax, 0, kMax2, @@ -5881,6 +6245,22 @@ procBlock procBlock::Split(const string &dir, const int &ind, const int &num, dt_.Slice(0, iMax, 0, jMax, kMinP2, kMaxP2)); blk2.residual_.Insert(0, iMax, 0, jMax, 0, kMax2, residual_.Slice(0, iMax, 0, jMax, kMinP2, kMaxP2)); + if (isViscous_) { + blk2.velocityGrad_.Insert(0, iMax, 0, jMax, 0, kMax2, + velocityGrad_.Slice(0, iMax, 0, jMax, kMinP2, + kMaxP2)); + blk2.temperatureGrad_.Insert(0, iMax, 0, jMax, 0, kMax2, + temperatureGrad_.Slice(0, iMax, 0, jMax, + kMinP2, kMaxP2)); + } + if (isTurbulent_) { + blk2.tkeGrad_.Insert(0, iMax, 0, jMax, 0, kMax2, + tkeGrad_.Slice(0, iMax, 0, jMax, kMinP2, kMaxP2)); + blk2.omegaGrad_.Insert(0, iMax, 0, jMax, 0, kMax2, + omegaGrad_.Slice(0, iMax, 0, jMax, kMinP2, + kMaxP2)); + } + // assign face variables blk2.fAreaI_.Insert(0, iMaxG + 1, 0, jMaxG, 0, kMaxG2, fAreaI_.Slice(0, iMaxG + 1, 0, jMaxG, kMinPG2, @@ -5911,7 +6291,7 @@ procBlock procBlock::Split(const string &dir, const int &ind, const int &num, } else { cerr << "ERROR: Error in procBlock::Split(). Direction " << dir << " is not recognized! Choose either i, j, or k." << endl; - exit(1); + exit(EXIT_FAILURE); } } @@ -5926,7 +6306,7 @@ void procBlock::Join(const procBlock &blk, const string &dir, if (dir == "i") { // -------------------------------------------------- procBlock newBlk(this->NumI() + blk.NumI(), this->NumJ(), this->NumK(), - numGhosts_); + numGhosts_, isViscous_, isTurbulent_); // cell indices const auto iMax = this->NumI() + blk.NumI() - 1; @@ -5958,6 +6338,22 @@ void procBlock::Join(const procBlock &blk, const string &dir, center_.Slice(0, iMaxLG, 0, jMaxG, 0, kMaxG)); newBlk.wallDist_.Insert(0, iMaxLG, 0, jMaxG, 0, kMaxG, wallDist_.Slice(0, iMaxLG, 0, jMaxG, 0, kMaxG)); + newBlk.temperature_.Insert(0, iMaxLG, 0, jMaxG, 0, kMaxG, + temperature_.Slice(0, iMaxLG, 0, jMaxG, 0, + kMaxG)); + if (isViscous_) { + newBlk.viscosity_.Insert(0, iMaxLG, 0, jMaxG, 0, kMaxG, + viscosity_.Slice(0, iMaxLG, 0, jMaxG, 0, kMaxG)); + } + if (isTurbulent_) { + newBlk.eddyViscosity_.Insert(0, iMaxLG, 0, jMaxG, 0, kMaxG, + eddyViscosity_.Slice(0, iMaxLG, 0, jMaxG, + 0, kMaxG)); + newBlk.f1_.Insert(0, iMaxLG, 0, jMaxG, 0, kMaxG, + f1_.Slice(0, iMaxLG, 0, jMaxG, 0, kMaxG)); + newBlk.f2_.Insert(0, iMaxLG, 0, jMaxG, 0, kMaxG, + f2_.Slice(0, iMaxLG, 0, jMaxG, 0, kMaxG)); + } // assign cell variables without ghost cells newBlk.specRadius_.Insert(0, iMaxL, 0, jMax, 0, kMax, @@ -5967,6 +6363,20 @@ void procBlock::Join(const procBlock &blk, const string &dir, dt_.Slice(0, iMaxL, 0, jMax, 0, kMax)); newBlk.residual_.Insert(0, iMaxL, 0, jMax, 0, kMax, residual_.Slice(0, iMaxL, 0, jMax, 0, kMax)); + if (isViscous_) { + newBlk.velocityGrad_.Insert(0, iMaxL, 0, jMax, 0, kMax, + velocityGrad_.Slice(0, iMaxL, 0, jMax, 0, + kMax)); + newBlk.temperatureGrad_.Insert(0, iMaxL, 0, jMax, 0, kMax, + temperatureGrad_.Slice(0, iMaxL, 0, + jMax, 0, kMax)); + } + if (isTurbulent_) { + newBlk.tkeGrad_.Insert(0, iMaxL, 0, jMax, 0, kMax, + tkeGrad_.Slice(0, iMaxL, 0, jMax, 0, kMax)); + newBlk.omegaGrad_.Insert(0, iMaxL, 0, jMax, 0, kMax, + omegaGrad_.Slice(0, iMaxL, 0, jMax, 0, kMax)); + } // assign face variables newBlk.fAreaI_.Insert(0, iMaxLG + 1, 0, jMaxG, 0, kMaxG, @@ -5995,6 +6405,23 @@ void procBlock::Join(const procBlock &blk, const string &dir, newBlk.wallDist_.Insert(iMaxLG + 1, iMaxG, 0, jMaxG, 0, kMaxG, blk.wallDist_.Slice(iMinUG, iMaxUG, 0, jMaxG, 0, kMaxG)); + newBlk.temperature_.Insert(iMaxLG + 1, iMaxG, 0, jMaxG, 0, kMaxG, + blk.temperature_.Slice(iMinUG, iMaxUG, 0, jMaxG, + 0, kMaxG)); + if (isViscous_) { + newBlk.viscosity_.Insert(iMaxLG + 1, iMaxG, 0, jMaxG, 0, kMaxG, + blk.viscosity_.Slice(iMinUG, iMaxUG, 0, jMaxG, 0, + kMaxG)); + } + if (isTurbulent_) { + newBlk.eddyViscosity_.Insert(iMaxLG + 1, iMaxG, 0, jMaxG, 0, kMaxG, + blk.eddyViscosity_.Slice(iMinUG, iMaxUG, 0, + jMaxG, 0, kMaxG)); + newBlk.f1_.Insert(iMaxLG + 1, iMaxG, 0, jMaxG, 0, kMaxG, + blk.f1_.Slice(iMinUG, iMaxUG, 0, jMaxG, 0, kMaxG)); + newBlk.f2_.Insert(iMaxLG + 1, iMaxG, 0, jMaxG, 0, kMaxG, + blk.f2_.Slice(iMinUG, iMaxUG, 0, jMaxG, 0, kMaxG)); + } // assign cell variables without ghost cells newBlk.specRadius_.Insert(iMaxL + 1, iMax, 0, jMax, 0, kMax, @@ -6004,6 +6431,22 @@ void procBlock::Join(const procBlock &blk, const string &dir, blk.dt_.Slice(0, iMaxU, 0, jMax, 0, kMax)); newBlk.residual_.Insert(iMaxL + 1, iMax, 0, jMax, 0, kMax, blk.residual_.Slice(0, iMaxU, 0, jMax, 0, kMax)); + if (isViscous_) { + newBlk.velocityGrad_.Insert(iMaxL + 1, iMax, 0, jMax, 0, kMax, + blk.velocityGrad_.Slice(0, iMaxU, 0, jMax, + 0, kMax)); + newBlk.temperatureGrad_.Insert(iMaxL + 1, iMax, 0, jMax, 0, kMax, + blk.temperatureGrad_.Slice(0, iMaxU, 0, + jMax, 0, + kMax)); + } + if (isTurbulent_) { + newBlk.tkeGrad_.Insert(iMaxL + 1, iMax, 0, jMax, 0, kMax, + blk.tkeGrad_.Slice(0, iMaxU, 0, jMax, 0, kMax)); + newBlk.omegaGrad_.Insert(iMaxL + 1, iMax, 0, jMax, 0, kMax, + blk.omegaGrad_.Slice(0, iMaxU, 0, jMax, 0, + kMax)); + } // assign face variables newBlk.fAreaI_.Insert(iMaxLG + 1, iMaxG + 1, 0, jMaxG, 0, kMaxG, @@ -6029,7 +6472,7 @@ void procBlock::Join(const procBlock &blk, const string &dir, *this = newBlk; } else if (dir == "j") { // ----------------------------------------- procBlock newBlk(this->NumI(), this->NumJ() + blk.NumJ(), this->NumK(), - numGhosts_); + numGhosts_, isViscous_, isTurbulent_); // cell indices const auto iMax = this->NumI() - 1; @@ -6061,6 +6504,21 @@ void procBlock::Join(const procBlock &blk, const string &dir, center_.Slice(0, iMaxG, 0, jMaxLG, 0, kMaxG)); newBlk.wallDist_.Insert(0, iMaxG, 0, jMaxLG, 0, kMaxG, wallDist_.Slice(0, iMaxG, 0, jMaxLG, 0, kMaxG)); + newBlk.temperature_.Insert(0, iMaxG, 0, jMaxLG, 0, kMaxG, + temperature_.Slice(0, iMaxG, 0, jMaxLG, 0, kMaxG)); + if (isViscous_) { + newBlk.viscosity_.Insert(0, iMaxG, 0, jMaxLG, 0, kMaxG, + viscosity_.Slice(0, iMaxG, 0, jMaxLG, 0, kMaxG)); + } + if (isTurbulent_) { + newBlk.eddyViscosity_.Insert(0, iMaxG, 0, jMaxLG, 0, kMaxG, + eddyViscosity_.Slice(0, iMaxG, 0, jMaxLG, 0, + kMaxG)); + newBlk.f1_.Insert(0, iMaxG, 0, jMaxLG, 0, kMaxG, + f1_.Slice(0, iMaxG, 0, jMaxLG, 0, kMaxG)); + newBlk.f2_.Insert(0, iMaxG, 0, jMaxLG, 0, kMaxG, + f2_.Slice(0, iMaxG, 0, jMaxLG, 0, kMaxG)); + } // assign cell variables without ghost cells newBlk.specRadius_.Insert(0, iMax, 0, jMaxL, 0, kMax, @@ -6070,6 +6528,20 @@ void procBlock::Join(const procBlock &blk, const string &dir, dt_.Slice(0, iMax, 0, jMaxL, 0, kMax)); newBlk.residual_.Insert(0, iMax, 0, jMaxL, 0, kMax, residual_.Slice(0, iMax, 0, jMaxL, 0, kMax)); + if (isViscous_) { + newBlk.velocityGrad_.Insert(0, iMax, 0, jMaxL, 0, kMax, + velocityGrad_.Slice(0, iMax, 0, jMaxL, + 0, kMax)); + newBlk.temperatureGrad_.Insert(0, iMax, 0, jMaxL, 0, kMax, + temperatureGrad_.Slice(0, iMax, 0, + jMaxL, 0, kMax)); + } + if (isTurbulent_) { + newBlk.tkeGrad_.Insert(0, iMax, 0, jMaxL, 0, kMax, + tkeGrad_.Slice(0, iMax, 0, jMaxL, 0, kMax)); + newBlk.omegaGrad_.Insert(0, iMax, 0, jMaxL, 0, kMax, + omegaGrad_.Slice(0, iMax, 0, jMaxL, 0, kMax)); + } // assign face variables newBlk.fAreaI_.Insert(0, iMaxG + 1, 0, jMaxLG, 0, kMaxG, @@ -6098,6 +6570,24 @@ void procBlock::Join(const procBlock &blk, const string &dir, newBlk.wallDist_.Insert(0, iMaxG, jMaxLG + 1, jMaxG, 0, kMaxG, blk.wallDist_.Slice(0, iMaxG, jMinUG, jMaxUG, 0, kMaxG)); + newBlk.temperature_.Insert(0, iMaxG, jMaxLG + 1, jMaxG, 0, kMaxG, + blk.temperature_.Slice(0, iMaxG, jMinUG, + jMaxUG, 0, + kMaxG)); + if (isViscous_) { + newBlk.viscosity_.Insert(0, iMaxG, jMaxLG + 1, jMaxG, 0, kMaxG, + blk.viscosity_.Slice(0, iMaxG, jMinUG, jMaxUG, 0, + kMaxG)); + } + if (isTurbulent_) { + newBlk.eddyViscosity_.Insert(0, iMaxG, jMaxLG + 1, jMaxG, 0, kMaxG, + blk.eddyViscosity_.Slice(0, iMaxG, jMinUG, + jMaxUG, 0, kMaxG)); + newBlk.f1_.Insert(0, iMaxG, jMaxLG + 1, jMaxG, 0, kMaxG, + blk.f1_.Slice(0, iMaxG, jMinUG, jMaxUG, 0, kMaxG)); + newBlk.f2_.Insert(0, iMaxG, jMaxLG + 1, jMaxG, 0, kMaxG, + blk.f2_.Slice(0, iMaxG, jMinUG, jMaxUG, 0, kMaxG)); + } // assign cell variables without ghost cells newBlk.specRadius_.Insert(0, iMax, jMaxL + 1, jMax, 0, kMax, @@ -6108,6 +6598,22 @@ void procBlock::Join(const procBlock &blk, const string &dir, newBlk.residual_.Insert(0, iMax, jMaxL + 1, jMax, 0, kMax, blk.residual_.Slice(0, iMax, 0, jMaxU, 0, kMax)); + if (isViscous_) { + newBlk.velocityGrad_.Insert(0, iMax, jMaxL + 1, jMax, 0, kMax, + blk.velocityGrad_.Slice(0, iMax, 0, jMaxU, + 0, kMax)); + newBlk.temperatureGrad_.Insert(0, iMax, jMaxL + 1, jMax, 0, kMax, + blk.temperatureGrad_.Slice(0, iMax, 0, + jMaxU, 0, kMax)); + } + if (isTurbulent_) { + newBlk.tkeGrad_.Insert(0, iMax, jMaxL + 1, jMax, 0, kMax, + blk.tkeGrad_.Slice(0, iMax, 0, jMaxU, 0, kMax)); + newBlk.omegaGrad_.Insert(0, iMax, jMaxL + 1, jMax, 0, kMax, + blk.omegaGrad_.Slice(0, iMax, 0, jMaxU, 0, + kMax)); + } + // assign face variables newBlk.fAreaI_.Insert(0, iMaxG + 1, jMaxLG + 1, jMaxG, 0, kMaxG, blk.fAreaI_.Slice(0, iMaxG + 1, jMinUG, jMaxUG, 0, @@ -6132,7 +6638,7 @@ void procBlock::Join(const procBlock &blk, const string &dir, *this = newBlk; } else if (dir == "k") { // ---------------------------------------------- procBlock newBlk(this->NumI(), this->NumJ(), this->NumK() + blk.NumK(), - numGhosts_); + numGhosts_, isViscous_, isTurbulent_); // cell indices const auto iMax = this->NumI() - 1; @@ -6164,6 +6670,22 @@ void procBlock::Join(const procBlock &blk, const string &dir, center_.Slice(0, iMaxG, 0, jMaxG, 0, kMaxLG)); newBlk.wallDist_.Insert(0, iMaxG, 0, jMaxG, 0, kMaxLG, wallDist_.Slice(0, iMaxG, 0, jMaxG, 0, kMaxLG)); + newBlk.temperature_.Insert(0, iMaxG, 0, jMaxG, 0, kMaxLG, + temperature_.Slice(0, iMaxG, 0, jMaxG, 0, + kMaxLG)); + if (isViscous_) { + newBlk.viscosity_.Insert(0, iMaxG, 0, jMaxG, 0, kMaxLG, + viscosity_.Slice(0, iMaxG, 0, jMaxG, 0, kMaxLG)); + } + if (isTurbulent_) { + newBlk.eddyViscosity_.Insert(0, iMaxG, 0, jMaxG, 0, kMaxLG, + eddyViscosity_.Slice(0, iMaxG, 0, jMaxG, 0, + kMaxLG)); + newBlk.f1_.Insert(0, iMaxG, 0, jMaxG, 0, kMaxLG, + f1_.Slice(0, iMaxG, 0, jMaxG, 0, kMaxLG)); + newBlk.f2_.Insert(0, iMaxG, 0, jMaxG, 0, kMaxLG, + f2_.Slice(0, iMaxG, 0, jMaxG, 0, kMaxLG)); + } // assign cell variables without ghost cells newBlk.specRadius_.Insert(0, iMax, 0, jMax, 0, kMaxL, @@ -6173,6 +6695,20 @@ void procBlock::Join(const procBlock &blk, const string &dir, dt_.Slice(0, iMax, 0, jMax, 0, kMaxL)); newBlk.residual_.Insert(0, iMax, 0, jMax, 0, kMaxL, residual_.Slice(0, iMax, 0, jMax, 0, kMaxL)); + if (isViscous_) { + newBlk.velocityGrad_.Insert(0, iMax, 0, jMax, 0, kMaxL, + velocityGrad_.Slice(0, iMax, 0, jMax, 0, + kMaxL)); + newBlk.temperatureGrad_.Insert(0, iMax, 0, jMax, 0, kMaxL, + temperatureGrad_.Slice(0, iMax, 0, jMax, + 0, kMaxL)); + } + if (isTurbulent_) { + newBlk.tkeGrad_.Insert(0, iMax, 0, jMax, 0, kMaxL, + tkeGrad_.Slice(0, iMax, 0, jMax, 0, kMaxL)); + newBlk.omegaGrad_.Insert(0, iMax, 0, jMax, 0, kMaxL, + omegaGrad_.Slice(0, iMax, 0, jMax, 0, kMaxL)); + } // assign face variables newBlk.fAreaI_.Insert(0, iMaxG + 1, 0, jMaxG, 0, kMaxLG, @@ -6201,6 +6737,23 @@ void procBlock::Join(const procBlock &blk, const string &dir, newBlk.wallDist_.Insert(0, iMaxG, 0, jMaxG, kMaxLG + 1, kMaxG, blk.wallDist_.Slice(0, iMaxG, 0, jMaxG, kMinUG, kMaxUG)); + newBlk.temperature_.Insert(0, iMaxG, 0, jMaxG, kMaxLG + 1, kMaxG, + blk.temperature_.Slice(0, iMaxG, 0, jMaxG, + kMinUG, kMaxUG)); + if (isViscous_) { + newBlk.viscosity_.Insert(0, iMaxG, 0, jMaxG, kMaxLG + 1, kMaxG, + blk.viscosity_.Slice(0, iMaxG, 0, jMaxG, kMinUG, + kMaxUG)); + } + if (isTurbulent_) { + newBlk.eddyViscosity_.Insert(0, iMaxG, 0, jMaxG, kMaxLG + 1, kMaxG, + blk.eddyViscosity_.Slice(0, iMaxG, 0, jMaxG, + kMinUG, kMaxUG)); + newBlk.f1_.Insert(0, iMaxG, 0, jMaxG, kMaxLG + 1, kMaxG, + blk.f1_.Slice(0, iMaxG, 0, jMaxG, kMinUG, kMaxUG)); + newBlk.f2_.Insert(0, iMaxG, 0, jMaxG, kMaxLG + 1, kMaxG, + blk.f2_.Slice(0, iMaxG, 0, jMaxG, kMinUG, kMaxUG)); + } // assign cell variables without ghost cells newBlk.specRadius_.Insert(0, iMax, 0, jMax, kMaxL + 1, kMax, @@ -6210,6 +6763,22 @@ void procBlock::Join(const procBlock &blk, const string &dir, blk.dt_.Slice(0, iMax, 0, jMax, 0, kMaxU)); newBlk.residual_.Insert(0, iMax, 0, jMax, kMaxL + 1, kMax, blk.residual_.Slice(0, iMax, 0, jMax, 0, kMaxU)); + if (isViscous_) { + newBlk.velocityGrad_.Insert(0, iMax, 0, jMax, kMaxL + 1, kMax, + blk.velocityGrad_.Slice(0, iMax, 0, jMax, 0, + kMaxU)); + newBlk.temperatureGrad_.Insert(0, iMax, 0, jMax, kMaxL + 1, kMax, + blk.temperatureGrad_.Slice(0, iMax, 0, + jMax, 0, + kMaxU)); + } + if (isTurbulent_) { + newBlk.tkeGrad_.Insert(0, iMax, 0, jMax, kMaxL + 1, kMax, + blk.tkeGrad_.Slice(0, iMax, 0, jMax, 0, kMaxU)); + newBlk.omegaGrad_.Insert(0, iMax, 0, jMax, kMaxL + 1, kMax, + blk.omegaGrad_.Slice(0, iMax, 0, jMax, 0, + kMaxU)); + } // assign face variables newBlk.fAreaI_.Insert(0, iMaxG + 1, 0, jMaxG, kMaxLG + 1, kMaxG, @@ -6236,20 +6805,17 @@ void procBlock::Join(const procBlock &blk, const string &dir, } else { cerr << "ERROR: Error in procBlock::Join(). Direction " << dir << " is not recognized! Choose either i, j, or k." << endl; - exit(1); + exit(EXIT_FAILURE); } } void procBlock::CalcGradsI(const int &ii, const int &jj, const int &kk, - const idealGas &eqnState, const bool &turbFlag, tensor &velGrad, vector3d &tGrad, vector3d &tkeGrad, vector3d &omegaGrad) const { // ii -- i-index for face (including ghosts) // jj -- j-index for face (including ghosts) // kk -- k-index for face (including ghosts) - // eqnState -- equation of state - // turbFlag -- flag to determine if simulation is turbulent // velGrad -- tensor to store velocity gradient // tGrad -- vector3d to store temperature gradient // tkeGrad -- vector3d to store tke gradient @@ -6294,35 +6860,35 @@ void procBlock::CalcGradsI(const int &ii, const int &jj, const int &kk, state_(ii - 1, jj, kk - 1).Velocity()); // Get velocity gradient at face - velGrad = CalcVelGradGG(state_(ii - 1, jj, kk).Velocity(), - state_(ii, jj, kk).Velocity(), vjl, vju, vkl, vku, - ail, aiu, ajl, aju, akl, aku, vol); + velGrad = VectorGradGG(state_(ii - 1, jj, kk).Velocity(), + state_(ii, jj, kk).Velocity(), vjl, vju, vkl, vku, + ail, aiu, ajl, aju, akl, aku, vol); // calculate average temperature on j and k faces of alternate control volume - const auto tju = 0.25 * (state_(ii - 1, jj, kk).Temperature(eqnState) + - state_(ii, jj, kk).Temperature(eqnState) + - state_(ii, jj + 1, kk).Temperature(eqnState) + - state_(ii - 1, jj + 1, kk).Temperature(eqnState)); - const auto tjl = 0.25 * (state_(ii - 1, jj, kk).Temperature(eqnState) + - state_(ii, jj, kk).Temperature(eqnState) + - state_(ii, jj - 1, kk).Temperature(eqnState) + - state_(ii - 1, jj - 1, kk).Temperature(eqnState)); - - const auto tku = 0.25 * (state_(ii - 1, jj, kk).Temperature(eqnState) + - state_(ii, jj, kk).Temperature(eqnState) + - state_(ii, jj, kk + 1).Temperature(eqnState) + - state_(ii - 1, jj, kk + 1).Temperature(eqnState)); - const auto tkl = 0.25 * (state_(ii - 1, jj, kk).Temperature(eqnState) + - state_(ii, jj, kk).Temperature(eqnState) + - state_(ii, jj, kk - 1).Temperature(eqnState) + - state_(ii - 1, jj, kk - 1).Temperature(eqnState)); + const auto tju = 0.25 * (temperature_(ii - 1, jj, kk) + + temperature_(ii, jj, kk) + + temperature_(ii, jj + 1, kk) + + temperature_(ii - 1, jj + 1, kk)); + const auto tjl = 0.25 * (temperature_(ii - 1, jj, kk) + + temperature_(ii, jj, kk) + + temperature_(ii, jj - 1, kk) + + temperature_(ii - 1, jj - 1, kk)); + + const auto tku = 0.25 * (temperature_(ii - 1, jj, kk) + + temperature_(ii, jj, kk) + + temperature_(ii, jj, kk + 1) + + temperature_(ii - 1, jj, kk + 1)); + const auto tkl = 0.25 * (temperature_(ii - 1, jj, kk) + + temperature_(ii, jj, kk) + + temperature_(ii, jj, kk - 1) + + temperature_(ii - 1, jj, kk - 1)); // Get temperature gradient at face - tGrad = CalcScalarGradGG(state_(ii - 1, jj, kk).Temperature(eqnState), - state_(ii, jj, kk).Temperature(eqnState), tjl, tju, - tkl, tku, ail, aiu, ajl, aju, akl, aku, vol); + tGrad = ScalarGradGG(temperature_(ii - 1, jj, kk), + temperature_(ii, jj, kk), tjl, tju, + tkl, tku, ail, aiu, ajl, aju, akl, aku, vol); - if (turbFlag) { + if (isTurbulent_) { // calculate average tke on j and k faces of alternate control volume const auto tkeju = 0.25 * (state_(ii - 1, jj, kk).Tke() + state_(ii, jj, kk).Tke() + @@ -6339,9 +6905,9 @@ void procBlock::CalcGradsI(const int &ii, const int &jj, const int &kk, state_(ii, jj, kk - 1).Tke() + state_(ii - 1, jj, kk - 1).Tke()); // Get tke gradient at face - tkeGrad = CalcScalarGradGG(state_(ii - 1, jj, kk).Tke(), - state_(ii, jj, kk).Tke(), tkejl, tkeju, tkekl, - tkeku, ail, aiu, ajl, aju, akl, aku, vol); + tkeGrad = ScalarGradGG(state_(ii - 1, jj, kk).Tke(), + state_(ii, jj, kk).Tke(), tkejl, tkeju, tkekl, + tkeku, ail, aiu, ajl, aju, akl, aku, vol); // calculate average Omega on j and k faces of alternate control volume const auto omgju = 0.25 * @@ -6359,22 +6925,19 @@ void procBlock::CalcGradsI(const int &ii, const int &jj, const int &kk, state_(ii, jj, kk - 1).Omega() + state_(ii - 1, jj, kk - 1).Omega()); // Get omega gradient at face - omegaGrad = CalcScalarGradGG( + omegaGrad = ScalarGradGG( state_(ii - 1, jj, kk).Omega(), state_(ii, jj, kk).Omega(), omgjl, omgju, omgkl, omgku, ail, aiu, ajl, aju, akl, aku, vol); } } void procBlock::CalcGradsJ(const int &ii, const int &jj, const int &kk, - const idealGas &eqnState, const bool &turbFlag, tensor &velGrad, vector3d &tGrad, vector3d &tkeGrad, vector3d &omegaGrad) const { // ii -- i-index for face (including ghosts) // jj -- j-index for face (including ghosts) // kk -- k-index for face (including ghosts) - // eqnState -- equation of state - // turbFlag -- flag to determine if simulation is turbulent // velGrad -- tensor to store velocity gradient // tGrad -- vector3d to store temperature gradient // tkeGrad -- vector3d to store tke gradient @@ -6419,36 +6982,35 @@ void procBlock::CalcGradsJ(const int &ii, const int &jj, const int &kk, state_(ii, jj - 1, kk - 1).Velocity()); // Get velocity gradient at face - velGrad = CalcVelGradGG(vil, viu, state_(ii, jj - 1, kk).Velocity(), - state_(ii, jj, kk).Velocity(), vkl, vku, ail, aiu, - ajl, aju, akl, aku, vol); + velGrad = VectorGradGG(vil, viu, state_(ii, jj - 1, kk).Velocity(), + state_(ii, jj, kk).Velocity(), vkl, vku, ail, aiu, + ajl, aju, akl, aku, vol); // calculate average temperature on i and k faces of alternate control volume - const auto tiu = 0.25 * (state_(ii, jj - 1, kk).Temperature(eqnState) + - state_(ii, jj, kk).Temperature(eqnState) + - state_(ii + 1, jj, kk).Temperature(eqnState) + - state_(ii + 1, jj - 1, kk).Temperature(eqnState)); - const auto til = 0.25 * (state_(ii, jj - 1, kk).Temperature(eqnState) + - state_(ii, jj, kk).Temperature(eqnState) + - state_(ii - 1, jj, kk).Temperature(eqnState) + - state_(ii - 1, jj - 1, kk).Temperature(eqnState)); - - const auto tku = 0.25 * (state_(ii, jj - 1, kk).Temperature(eqnState) + - state_(ii, jj, kk).Temperature(eqnState) + - state_(ii, jj, kk + 1).Temperature(eqnState) + - state_(ii, jj - 1, kk + 1).Temperature(eqnState)); - const auto tkl = 0.25 * (state_(ii, jj - 1, kk).Temperature(eqnState) + - state_(ii, jj, kk).Temperature(eqnState) + - state_(ii, jj, kk - 1).Temperature(eqnState) + - state_(ii, jj - 1, kk - 1).Temperature(eqnState)); + const auto tiu = 0.25 * (temperature_(ii, jj - 1, kk) + + temperature_(ii, jj, kk) + + temperature_(ii + 1, jj, kk) + + temperature_(ii + 1, jj - 1, kk)); + const auto til = 0.25 * (temperature_(ii, jj - 1, kk) + + temperature_(ii, jj, kk) + + temperature_(ii - 1, jj, kk) + + temperature_(ii - 1, jj - 1, kk)); + + const auto tku = 0.25 * (temperature_(ii, jj - 1, kk) + + temperature_(ii, jj, kk) + + temperature_(ii, jj, kk + 1) + + temperature_(ii, jj - 1, kk + 1)); + const auto tkl = 0.25 * (temperature_(ii, jj - 1, kk) + + temperature_(ii, jj, kk) + + temperature_(ii, jj, kk - 1) + + temperature_(ii, jj - 1, kk - 1)); // Get temperature gradient at face - tGrad = CalcScalarGradGG(til, tiu, - state_(ii, jj - 1, kk).Temperature(eqnState), - state_(ii, jj, kk).Temperature(eqnState), tkl, tku, - ail, aiu, ajl, aju, akl, aku, vol); + tGrad = ScalarGradGG(til, tiu, temperature_(ii, jj - 1, kk), + temperature_(ii, jj, kk), tkl, tku, + ail, aiu, ajl, aju, akl, aku, vol); - if (turbFlag) { + if (isTurbulent_) { // calculate average tke on i and k faces of alternate control volume const auto tkeiu = 0.25 * (state_(ii, jj - 1, kk).Tke() + state_(ii, jj, kk).Tke() + @@ -6465,9 +7027,9 @@ void procBlock::CalcGradsJ(const int &ii, const int &jj, const int &kk, state_(ii, jj, kk - 1).Tke() + state_(ii, jj - 1, kk - 1).Tke()); // Get temperature gradient at face - tkeGrad = CalcScalarGradGG(tkeil, tkeiu, state_(ii, jj - 1, kk).Tke(), - state_(ii, jj, kk).Tke(), tkekl, tkeku, ail, aiu, - ajl, aju, akl, aku, vol); + tkeGrad = ScalarGradGG(tkeil, tkeiu, state_(ii, jj - 1, kk).Tke(), + state_(ii, jj, kk).Tke(), tkekl, tkeku, ail, aiu, + ajl, aju, akl, aku, vol); // calculate average omega on i and k faces of alternate control volume const auto omgiu = 0.25 * @@ -6485,22 +7047,19 @@ void procBlock::CalcGradsJ(const int &ii, const int &jj, const int &kk, state_(ii, jj, kk - 1).Omega() + state_(ii, jj - 1, kk - 1).Omega()); // Get temperature gradient at face - omegaGrad = CalcScalarGradGG(omgil, omgiu, state_(ii, jj - 1, kk).Omega(), - state_(ii, jj, kk).Omega(), omgkl, omgku, ail, - aiu, ajl, aju, akl, aku, vol); + omegaGrad = ScalarGradGG(omgil, omgiu, state_(ii, jj - 1, kk).Omega(), + state_(ii, jj, kk).Omega(), omgkl, omgku, ail, + aiu, ajl, aju, akl, aku, vol); } } void procBlock::CalcGradsK(const int &ii, const int &jj, const int &kk, - const idealGas &eqnState, const bool &turbFlag, tensor &velGrad, vector3d &tGrad, vector3d &tkeGrad, vector3d &omegaGrad) const { // ii -- i-index for face (including ghosts) // jj -- j-index for face (including ghosts) // kk -- k-index for face (including ghosts) - // eqnState -- equation of state - // turbFlag -- flag to determine if simulation is turbulent // velGrad -- tensor to store velocity gradient // tGrad -- vector3d to store temperature gradient // tkeGrad -- vector3d to store tke gradient @@ -6537,7 +7096,7 @@ void procBlock::CalcGradsK(const int &ii, const int &jj, const int &kk, const auto vju = 0.25 * (state_(ii, jj, kk - 1).Velocity() + state_(ii, jj, kk).Velocity() + - state_(ii, jj, kk + 1).Velocity() + + state_(ii, jj + 1, kk).Velocity() + state_(ii, jj + 1, kk - 1).Velocity()); const auto vjl = 0.25 * (state_(ii, jj, kk - 1).Velocity() + state_(ii, jj, kk).Velocity() + @@ -6545,36 +7104,35 @@ void procBlock::CalcGradsK(const int &ii, const int &jj, const int &kk, state_(ii, jj - 1, kk - 1).Velocity()); // Get velocity gradient at face - velGrad = CalcVelGradGG(vil, viu, vjl, vju, state_(ii, jj, kk - 1).Velocity(), - state_(ii, jj, kk).Velocity(), ail, aiu, ajl, aju, - akl, aku, vol); + velGrad = VectorGradGG(vil, viu, vjl, vju, state_(ii, jj, kk - 1).Velocity(), + state_(ii, jj, kk).Velocity(), ail, aiu, ajl, aju, + akl, aku, vol); // calculate average temperature on i and j faces of alternate control volume - const auto tiu = 0.25 * (state_(ii, jj, kk - 1).Temperature(eqnState) + - state_(ii, jj, kk).Temperature(eqnState) + - state_(ii + 1, jj, kk).Temperature(eqnState) + - state_(ii + 1, jj, kk - 1).Temperature(eqnState)); - const auto til = 0.25 * (state_(ii, jj, kk - 1).Temperature(eqnState) + - state_(ii, jj, kk).Temperature(eqnState) + - state_(ii - 1, jj, kk).Temperature(eqnState) + - state_(ii - 1, jj, kk - 1).Temperature(eqnState)); - - const auto tju = 0.25 * (state_(ii, jj, kk - 1).Temperature(eqnState) + - state_(ii, jj, kk).Temperature(eqnState) + - state_(ii, jj, kk + 1).Temperature(eqnState) + - state_(ii, jj + 1, kk - 1).Temperature(eqnState)); - const auto tjl = 0.25 * (state_(ii, jj, kk - 1).Temperature(eqnState) + - state_(ii, jj, kk).Temperature(eqnState) + - state_(ii, jj - 1, kk).Temperature(eqnState) + - state_(ii, jj - 1, kk - 1).Temperature(eqnState)); + const auto tiu = 0.25 * (temperature_(ii, jj, kk - 1) + + temperature_(ii, jj, kk) + + temperature_(ii + 1, jj, kk) + + temperature_(ii + 1, jj, kk - 1)); + const auto til = 0.25 * (temperature_(ii, jj, kk - 1) + + temperature_(ii, jj, kk) + + temperature_(ii - 1, jj, kk) + + temperature_(ii - 1, jj, kk - 1)); + + const auto tju = 0.25 * (temperature_(ii, jj, kk - 1) + + temperature_(ii, jj, kk) + + temperature_(ii, jj + 1, kk) + + temperature_(ii, jj + 1, kk - 1)); + const auto tjl = 0.25 * (temperature_(ii, jj, kk - 1) + + temperature_(ii, jj, kk) + + temperature_(ii, jj - 1, kk) + + temperature_(ii, jj - 1, kk - 1)); // Get temperature gradient at face - tGrad = CalcScalarGradGG(til, tiu, tjl, tju, - state_(ii, jj, kk - 1).Temperature(eqnState), - state_(ii, jj, kk).Temperature(eqnState), ail, aiu, - ajl, aju, akl, aku, vol); + tGrad = ScalarGradGG(til, tiu, tjl, tju, temperature_(ii, jj, kk - 1), + temperature_(ii, jj, kk), ail, aiu, + ajl, aju, akl, aku, vol); - if (turbFlag) { + if (isTurbulent_) { // calculate average tke on i and j faces of alternate control volume const auto tkeiu = 0.25 * (state_(ii, jj, kk - 1).Tke() + state_(ii, jj, kk).Tke() + @@ -6585,13 +7143,13 @@ void procBlock::CalcGradsK(const int &ii, const int &jj, const int &kk, const auto tkeju = 0.25 * (state_(ii, jj, kk - 1).Tke() + state_(ii, jj, kk).Tke() + - state_(ii, jj, kk + 1).Tke() + state_(ii, jj + 1, kk - 1).Tke()); + state_(ii, jj + 1, kk).Tke() + state_(ii, jj + 1, kk - 1).Tke()); const auto tkejl = 0.25 * (state_(ii, jj, kk - 1).Tke() + state_(ii, jj, kk).Tke() + state_(ii, jj - 1, kk).Tke() + state_(ii, jj - 1, kk - 1).Tke()); // Get temperature gradient at face - tkeGrad = CalcScalarGradGG( + tkeGrad = ScalarGradGG( tkeil, tkeiu, tkejl, tkeju, state_(ii, jj, kk - 1).Tke(), state_(ii, jj, kk).Tke(), ail, aiu, ajl, aju, akl, aku, vol); @@ -6605,27 +7163,24 @@ void procBlock::CalcGradsK(const int &ii, const int &jj, const int &kk, const auto omgju = 0.25 * (state_(ii, jj, kk - 1).Omega() + state_(ii, jj, kk).Omega() + - state_(ii, jj, kk + 1).Omega() + state_(ii, jj + 1, kk - 1).Omega()); + state_(ii, jj + 1, kk).Omega() + state_(ii, jj + 1, kk - 1).Omega()); const auto omgjl = 0.25 * (state_(ii, jj, kk - 1).Omega() + state_(ii, jj, kk).Omega() + state_(ii, jj - 1, kk).Omega() + state_(ii, jj - 1, kk - 1).Omega()); // Get temperature gradient at face - omegaGrad = CalcScalarGradGG( + omegaGrad = ScalarGradGG( omgil, omgiu, omgjl, omgju, state_(ii, jj, kk - 1).Omega(), state_(ii, jj, kk).Omega(), ail, aiu, ajl, aju, akl, aku, vol); } } // Member function to calculate the source terms and add them to the residual -void procBlock::CalcSrcTerms(const gradients &grads, const sutherland &suth, - const idealGas &eos, +void procBlock::CalcSrcTerms(const sutherland &suth, const unique_ptr &turb, const input &inp, multiArray3d &mainDiagonal) { - // grads -- gradients (vel, temp, tke, omega) // suth -- sutherland's law for viscosity - // eos -- equation of state // turb -- turbulence model // mainDiagonal -- main diagonal of LHS used to store flux jacobians for // implicit solver @@ -6636,100 +7191,38 @@ void procBlock::CalcSrcTerms(const gradients &grads, const sutherland &suth, for (auto ip = 0, ig = numGhosts_; ip < this->NumI(); ig++, ip++) { // calculate turbulent source terms source src; - src.CalcTurbSrc(turb, state_(ig, jg, kg), grads, suth, eos, - wallDist_(ig, jg, kg), vol_(ig, jg, kg), ip, jp, kp); + const auto srcJac = src.CalcTurbSrc(turb, state_(ig, jg, kg), + velocityGrad_(ip, jp, kp), + temperatureGrad_(ip, jp, kp), + tkeGrad_(ip, jp, kp), + omegaGrad_(ip, jp, kp), suth, + vol_(ig, jg, kg), + eddyViscosity_(ig, jg, kg), + f1_(ig, jg, kg)); // add source terms to residual // subtract because residual is initially on opposite side of equation - this->SubtractFromResidual(src * (vol_(ig, jg, kg)), + this->SubtractFromResidual(src * vol_(ig, jg, kg), ip, jp, kp); // add source spectral radius for turbulence equations - const auto srcSpecRad = turb->SrcSpecRad(state_(ig, jg, kg), suth, - vol_(ig, jg, kg)); - specRadius_(ip, jp, kp).SubtractFromTurbVariable(srcSpecRad); + // subtract because residual is initially on opposite side of equation + const auto turbSpecRad = turb->SrcSpecRad(state_(ig, jg, kg), suth, + vol_(ig, jg, kg)); + specRadius_(ip, jp, kp).SubtractFromTurbVariable(turbSpecRad); // add contribution of source spectral radius to flux jacobian if (inp.IsBlockMatrix()) { - // mainDiagonal(ip, jp, kp).AddTurbSourceJacobian( - // state_(ig, jg, kg), suth, vol_(ig, jg, kg), turb); + mainDiagonal(ip, jp, kp).SubtractFromTurbJacobian(srcJac); } else { - const uncoupledScalar srcJac(0.0, srcSpecRad); - mainDiagonal(ip, jp, kp) -= fluxJacobian(srcJac); + const uncoupledScalar srcJacScalar(0.0, turbSpecRad); + mainDiagonal(ip, jp, kp) -= fluxJacobian(srcJacScalar); } } } } } -// function to get face centers of cells on viscous walls -vector> GetViscousFaceCenters(const vector &blks) { - // blks -- vector of all procBlocks in simulation - - // get vector of BCs - vector bcs; - bcs.reserve(blks.size()); - for (auto ii = 0; ii < static_cast(blks.size()); ii++) { - bcs.push_back(blks[ii].BC()); - } - - // determine number of faces with viscous wall BC - auto nFaces = 0; - for (auto ii = 0; ii < static_cast(bcs.size()); ii++) { - nFaces += bcs[ii].NumViscousFaces(); - } - - // allocate vector for face centers - vector> faceCenters; - faceCenters.reserve(nFaces); - - const auto numG = blks[0].NumGhosts(); // number of ghost cells - - // store viscous face centers - for (auto aa = 0; aa < static_cast(bcs.size()); aa++) { // loop over BCs - for (auto bb = 0; bb < bcs[aa].NumSurfaces(); bb++) { // loop over surfaces - if (bcs[aa].GetBCTypes(bb) == "viscousWall") { - // only store face center if surface is viscous wall - - if (bcs[aa].GetSurfaceType(bb) <= 2) { // i-surface - const auto ii = (bcs[aa].GetSurfaceType(bb) % 2 == 0) - ? blks[aa].NumI() + numG : numG; - - for (auto jj = bcs[aa].GetJMin(bb) - 1 + numG; - jj < bcs[aa].GetJMax(bb) - 1 + numG; jj++) { - for (auto kk = bcs[aa].GetKMin(bb) - 1 + numG; - kk < bcs[aa].GetKMax(bb) - 1 + numG; kk++) { - faceCenters.push_back(blks[aa].FCenterI(ii, jj, kk)); - } - } - } else if (bcs[aa].GetSurfaceType(bb) <= 4) { // j-surface - const auto jj = (bcs[aa].GetSurfaceType(bb) % 2 == 0) - ? blks[aa].NumJ() + numG : numG; - - for (auto ii = bcs[aa].GetIMin(bb) - 1 + numG; - ii < bcs[aa].GetIMax(bb) - 1 + numG; ii++) { - for (auto kk = bcs[aa].GetKMin(bb) - 1 + numG; - kk < bcs[aa].GetKMax(bb) - 1 + numG; kk++) { - faceCenters.push_back(blks[aa].FCenterJ(ii, jj, kk)); - } - } - } else { // k-surface - const auto kk = (bcs[aa].GetSurfaceType(bb) % 2 == 0) - ? blks[aa].NumK() + numG : numG; - - for (auto ii = bcs[aa].GetIMin(bb) - 1 + numG; - ii < bcs[aa].GetIMax(bb) - 1 + numG; ii++) { - for (auto jj = bcs[aa].GetJMin(bb) - 1 + numG; - jj < bcs[aa].GetJMax(bb) - 1 + numG; jj++) { - faceCenters.push_back(blks[aa].FCenterK(ii, jj, kk)); - } - } - } - } - } - } - return faceCenters; -} // member function to calculate the distance to the nearest viscous wall of // all cell centers @@ -6739,232 +7232,124 @@ void procBlock::CalcWallDistance(const kdtree &tree) { for (auto kk = 0; kk < wallDist_.NumK(); kk++) { for (auto jj = 0; jj < wallDist_.NumJ(); jj++) { for (auto ii = 0; ii < wallDist_.NumI(); ii++) { - wallDist_(ii, jj, kk) = + // ghost cells should have negative wall distance so that wall distance + // at viscous face will be 0 during flux calculation + auto fac = this->IsPhysical(ii, jj, kk, true) ? 1.0 : -1.0; + wallDist_(ii, jj, kk) = fac * tree.NearestNeighbor(center_(ii, jj, kk), neighbor); } } } } -// member function to calculate the residual (LHS) -void procBlock::CalcResidual(const sutherland &suth, const idealGas &eos, - const input &inp, - const unique_ptr &turb, - multiArray3d &mainDiagonal) { +// member function to calculate the residual (RHS) excluding any contributions +// from source terms +void procBlock::CalcResidualNoSource(const sutherland &suth, + const idealGas &eos, + const input &inp, + const unique_ptr &turb, + multiArray3d &mainDiagonal) { + // Zero spectral radii, residuals, gradients, turbulence variables + this->ResetResidWS(); + if (isViscous_) { + this->ResetGradients(); + if (isTurbulent_) { + this->ResetTurbVars(); + } + } + // Calculate inviscid fluxes this->CalcInvFluxI(eos, inp, turb, mainDiagonal); this->CalcInvFluxJ(eos, inp, turb, mainDiagonal); this->CalcInvFluxK(eos, inp, turb, mainDiagonal); // If viscous change ghost cells and calculate viscous fluxes - if (inp.IsViscous()) { + if (isViscous_) { // Determine ghost cell values for viscous fluxes - this->AssignViscousGhostCells(inp, eos, suth, - turb); + this->AssignViscousGhostCells(inp, eos, suth, turb); - // Calculate gradients - gradients grads(inp.IsTurbulent(), *this, eos); + // Update temperature and viscosity + this->UpdateAuxillaryVariables(eos, suth); // Calculate viscous fluxes - this->CalcViscFluxI(suth, eos, inp, grads, turb, mainDiagonal); - this->CalcViscFluxJ(suth, eos, inp, grads, turb, mainDiagonal); - this->CalcViscFluxK(suth, eos, inp, grads, turb, mainDiagonal); + this->CalcViscFluxI(suth, eos, inp, turb, mainDiagonal); + this->CalcViscFluxJ(suth, eos, inp, turb, mainDiagonal); + this->CalcViscFluxK(suth, eos, inp, turb, mainDiagonal); - // If turblent, calculate source terms - if (inp.IsTurbulent()) { - this->CalcSrcTerms(grads, suth, eos, turb, inp, mainDiagonal); - } - } -} - - -// function to calculate the distance to the nearest viscous wall of all -// cell centers -void CalcWallDistance(vector &localBlocks, const kdtree &tree) { - for (auto &block : localBlocks) { - block.CalcWallDistance(tree); + } else { + // Update temperature + this->UpdateAuxillaryVariables(eos, suth); } } -// function to take in a vector of procBlocks and return a vector of the -// conservative variable states -vector> GetCopyConsVars(const vector &blocks, - const idealGas &eos) { - vector> consVars(blocks.size()); - for (auto ii = 0; ii < static_cast(blocks.size()); ii++) { - consVars[ii] = blocks[ii].GetCopyConsVars(eos); - } - return consVars; -} - -void ExplicitUpdate(vector &blocks, - const input &inp, const idealGas &eos, - const double &aRef, const sutherland &suth, - const vector> &solTimeN, - const unique_ptr &turb, const int &mm, - genArray &residL2, resid &residLinf) { - // create dummy update (not used in explicit update) - multiArray3d du(1, 1, 1); - // loop over all blocks: update and reset residuals / wave speed - for (auto bb = 0; bb < static_cast(blocks.size()); bb++) { - blocks[bb].UpdateBlock(inp, eos, aRef, suth, du, solTimeN[bb], - turb, mm, residL2, residLinf); - blocks[bb].ResetResidWS(); - } +// member function to get a slice of the state variables +multiArray3d procBlock::SliceState(const int &is, const int &ie, + const int &js, const int &je, + const int &ks, + const int &ke) const { + return state_.Slice(is, ie, js, je, ks, ke); } - -double ImplicitUpdate(vector &blocks, - vector> &mainDiagonal, - const input &inp, const idealGas &eos, - const double &aRef, const sutherland &suth, - const vector> &solTimeN, - const vector> &solDeltaMmN, - vector> &solDeltaNm1, - const unique_ptr &turb, const int &mm, - genArray &residL2, resid &residLinf, - const vector &connections, const int &rank, - const MPI_Datatype &MPI_cellData) { - // blocks -- vector of procBlocks on current processor - // mainDiagonal -- main diagonal of A matrix for all blocks on processor - // inp -- input variables - // eos -- equation of state - // suth -- sutherland's law for viscosity - // solTimeN -- solution at time N - // solDeltaMmN -- solution at time M minus solution at time N - // solDeltaNm1 -- solution at time N minus 1 - // turb -- turbulence model - // mm -- nonlinear iteration - // residL2 -- L2 residual - // residLinf -- L infinity residual - - // initialize matrix error - auto matrixError = 0.0; - - const auto numG = blocks[0].NumGhosts(); - - // add volume and time term and calculate inverse of main diagonal - for (auto bb = 0; bb < static_cast(blocks.size()); bb++) { - blocks[bb].InvertDiagonal(mainDiagonal[bb], inp); - } - - // initialize matrix update - vector> du(blocks.size()); - for (auto bb = 0; bb < static_cast(blocks.size()); bb++) { - du[bb] = blocks[bb].InitializeMatrixUpdate(inp, solDeltaMmN[bb], - solDeltaNm1[bb], - mainDiagonal[bb]); - } - - // Solve Ax=b with supported solver - if (inp.MatrixSolver() == "lusgs") { - // calculate order by hyperplanes for each block - vector>> reorder(blocks.size()); - for (auto bb = 0; bb < static_cast(blocks.size()); bb++) { - reorder[bb] = HyperplaneReorder(blocks[bb].NumI(), blocks[bb].NumJ(), - blocks[bb].NumK()); - } - - // start sweeps through domain - for (auto ii = 0; ii < inp.MatrixSweeps(); ii++) { - // swap updates for ghost cells - SwapImplicitUpdate(du, connections, rank, MPI_cellData, numG); - - // forward lu-sgs sweep - for (auto bb = 0; bb < static_cast(blocks.size()); bb++) { - blocks[bb].LUSGS_Forward(reorder[bb], du[bb], solDeltaMmN[bb], - solDeltaNm1[bb], eos, inp, suth, turb, - mainDiagonal[bb], ii); - } - - // swap updates for ghost cells - SwapImplicitUpdate(du, connections, rank, MPI_cellData, numG); - - // backward lu-sgs sweep - for (auto bb =0; bb < static_cast(blocks.size()); bb++) { - matrixError += blocks[bb].LUSGS_Backward(reorder[bb], du[bb], - solDeltaMmN[bb], - solDeltaNm1[bb], eos, inp, - suth, turb, mainDiagonal[bb], ii); - } - } - } else if (inp.MatrixSolver() == "dplur") { - for (auto ii = 0; ii < inp.MatrixSweeps(); ii++) { - // swap updates for ghost cells - SwapImplicitUpdate(du, connections, rank, MPI_cellData, numG); - - for (auto bb = 0; bb < static_cast(blocks.size()); bb++) { - // Calculate correction (du) - matrixError += blocks[bb].DPLUR(du[bb], solDeltaMmN[bb], - solDeltaNm1[bb], eos, inp, suth, turb, - mainDiagonal[bb]); +void procBlock::UpdateAuxillaryVariables(const idealGas &eos, + const sutherland &suth, + const bool includeGhosts) { + for (auto kg = 0; kg < this->NumKG(); kg++) { + for (auto jg = 0; jg < this->NumJG(); jg++) { + for (auto ig = 0; ig < this->NumIG(); ig++) { + if (!this->AtCorner(ig, jg, kg, true) && + (includeGhosts || this->IsPhysical(ig, jg, kg, true))) { + temperature_(ig, jg, kg) = state_(ig, jg, kg).Temperature(eos); + if (isViscous_) { + viscosity_(ig, jg, kg) = suth.Viscosity(temperature_(ig, jg, kg)); + } + } } } - } else { - cerr << "ERROR: Matrix solver " << inp.MatrixSolver() << - " is not recognized!" << endl; - cerr << "Please choose lusgs or dplur." << endl; - exit(1); } - - // Update blocks and reset residuals and wave speeds - for (auto bb = 0; bb < static_cast(blocks.size()); bb++) { - // Update solution - blocks[bb].UpdateBlock(inp, eos, aRef, suth, du[bb], solTimeN[bb], - turb, mm, residL2, residLinf); - - // Assign time n to time n-1 at end of nonlinear iterations - if (inp.TimeIntegration() == "bdf2" && - mm == inp.NonlinearIterations() - 1 ) { - solDeltaNm1[bb] = blocks[bb].DeltaNMinusOne(solTimeN[bb], eos, - inp.Theta(), inp.Zeta()); - } - - // Zero residuals, wave speed, flux jacobians, and update - blocks[bb].ResetResidWS(); - mainDiagonal[bb].Zero(fluxJacobian(0.0, 0.0)); - } - - return matrixError; } -void SwapImplicitUpdate(vector> &du, - const vector &connections, const int &rank, - const MPI_Datatype &MPI_cellData, - const int &numGhosts) { - // du -- implicit update in conservative variables - // connections -- interblock boundary conditions - // rank -- processor rank - // MPI_cellData -- datatype to pass primVars or genArray - // numGhosts -- number of ghost cells - - // loop over all connections and swap interblock updates when necessary - for (auto ii = 0; ii < static_cast(connections.size()); ii++) { - if (connections[ii].RankFirst() == rank && - connections[ii].RankSecond() == rank) { - // both sides of interblock are on this processor, swap w/o mpi - du[connections[ii].LocalBlockFirst()].SwapSlice(connections[ii], - du[connections[ii].LocalBlockSecond()], numGhosts, numGhosts); - } else if (connections[ii].RankFirst() == rank) { - // rank matches rank of first side of interblock, swap over mpi - du[connections[ii].LocalBlockFirst()] - .SwapSliceMPI(connections[ii], rank, MPI_cellData, numGhosts); - - } else if (connections[ii].RankSecond() == rank) { - // rank matches rank of second side of interblock, swap over mpi - du[connections[ii].LocalBlockSecond()] - .SwapSliceMPI(connections[ii], rank, MPI_cellData, numGhosts); +void procBlock::UpdateUnlimTurbEddyVisc(const unique_ptr &turb, + const bool &includeGhosts) { + if (isTurbulent_) { + for (auto kg = 0; kg < this->NumKG(); kg++) { + for (auto jg = 0; jg < this->NumJG(); jg++) { + for (auto ig = 0; ig < this->NumIG(); ig++) { + if (!this->AtCorner(ig, jg, kg, true) && + (includeGhosts || this->IsPhysical(ig, jg, kg, true))) { + eddyViscosity_(ig, jg, kg) = turb->EddyViscNoLim(state_(ig, jg, kg)); + } + } + } } - // if rank doesn't match either side of interblock, then do nothing and - // move on to the next interblock } } -multiArray3d procBlock::SliceState(const int &is, const int &ie, - const int &js, const int &je, - const int &ks, - const int &ke) const { - return state_.Slice(is, ie, js, je, ks, ke); +// member function to calculate the center to center distance across a cell face +// projected along that face's area vector +double procBlock::ProjC2CDist(const int &ig, const int &jg, const int &kg, + const string &dir) const { + // ig -- cell face index in i-direction + // jg -- cell face index in j-direction + // kg -- cell face index in k-direction + // dir -- direction of face (i, j, or k) + + auto projDist = 0.0; + // always subtract "higher" center from "lower" center because area vector + // points from lower to higher + if (dir == "i") { + const auto c2cVec = this->Center(ig, jg, kg) - this->Center(ig - 1, jg, kg); + projDist = c2cVec.DotProd(this->FAreaUnitI(ig, jg, kg)); + } else if (dir == "j") { + const auto c2cVec = this->Center(ig, jg, kg) - this->Center(ig, jg - 1, kg); + projDist = c2cVec.DotProd(this->FAreaUnitJ(ig, jg, kg)); + } else if (dir == "k") { + const auto c2cVec = this->Center(ig, jg, kg) - this->Center(ig, jg, kg - 1); + projDist = c2cVec.DotProd(this->FAreaUnitK(ig, jg, kg)); + } else { + cerr << "ERROR: Error in procBlock::ProjC2CDist(). Direction " << dir + << " is not recognized. Please choose i, j, or k." << endl; + exit(EXIT_FAILURE); + } + return projDist; } - diff --git a/procBlock.hpp b/procBlock.hpp index a8e49ea..d444bcb 100644 --- a/procBlock.hpp +++ b/procBlock.hpp @@ -31,7 +31,6 @@ #include "genArray.hpp" // genArray #include "boundaryConditions.hpp" // interblock, patch #include "macros.hpp" -#include "kdtree.hpp" // kdtree #include "uncoupledScalar.hpp" // uncoupledScalar using std::vector; @@ -49,13 +48,13 @@ class sutherland; class inviscidFlux; class viscousFlux; class input; -class gradients; class geomSlice; class source; class turbModel; class plot3dBlock; class resid; class fluxJacobian; +class kdtree; class procBlock { multiArray3d state_; // primative variables at cell center @@ -76,6 +75,19 @@ class procBlock { multiArray3d dt_; // cell time step multiArray3d wallDist_; // distance to nearest viscous wall + // gradients + multiArray3d> velocityGrad_; + multiArray3d> temperatureGrad_; + multiArray3d> tkeGrad_; + multiArray3d> omegaGrad_; + + // auxillary variables + multiArray3d temperature_; + multiArray3d viscosity_; + multiArray3d eddyViscosity_; + multiArray3d f1_; + multiArray3d f2_; + boundaryConditions bc_; // boundary conditions for block int numGhosts_; // number of layers of ghost cells surrounding block @@ -84,6 +96,9 @@ class procBlock { int localPos_; // position on local processor int globalPos_; // global position of procBlock in decomposed vector of // procBlocks + bool isViscous_; + bool isTurbulent_; + // private member functions void CalcInvFluxI(const idealGas &, const input &, @@ -97,13 +112,13 @@ class procBlock { multiArray3d &); void CalcViscFluxI(const sutherland &, const idealGas &, const input &, - const gradients &, const unique_ptr &, + const unique_ptr &, multiArray3d &); void CalcViscFluxJ(const sutherland &, const idealGas &, const input &, - const gradients &, const unique_ptr &, + const unique_ptr &, multiArray3d &); void CalcViscFluxK(const sutherland &, const idealGas &, const input &, - const gradients &, const unique_ptr &, + const unique_ptr &, multiArray3d &); void CalcCellDt(const int &, const int &, const int &, const double &); @@ -119,10 +134,6 @@ class procBlock { const int &, const int &, const int &, const int &, const int &); - void CalcSrcTerms(const gradients &, const sutherland &, const idealGas &, - const unique_ptr &, const input &, - multiArray3d &); - void AddToResidual(const inviscidFlux &, const int &, const int &, const int &); void AddToResidual(const viscousFlux &, const int &, const int &, @@ -134,12 +145,15 @@ class procBlock { void SubtractFromResidual(const source &, const int &, const int &, const int &); + public: // constructors procBlock(const primVars &, const plot3dBlock &, const int &, const int &, - const boundaryConditions &, const int &, const int &, const int &); - procBlock(const int &, const int &, const int &, const int &); - procBlock() : procBlock(1, 1, 1, 0) {} + const boundaryConditions &, const int &, const int &, const int &, + const input &, const idealGas &, const sutherland &); + procBlock(const int &, const int &, const int &, const int &, const bool &, + const bool &); + procBlock() : procBlock(1, 1, 1, 0, false, false) {} // move constructor and assignment operator procBlock(procBlock&&) noexcept = default; @@ -163,7 +177,9 @@ class procBlock { int LocalPosition() const { return localPos_; } int Rank() const { return rank_; } int GlobalPos() const { return globalPos_; } - + bool IsViscous() const { return isViscous_; } + bool IsTurbulent() const { return isTurbulent_; } + boundaryConditions BC() const { return bc_; } primVars State(const int &ii, const int &jj, const int &kk) const { @@ -245,6 +261,36 @@ class procBlock { return residual_(ii, jj, kk)[a]; } + tensor VelGrad(const int &ii, const int &jj, const int &kk) const { + return velocityGrad_(ii, jj, kk); + } + vector3d TempGrad(const int &ii, const int &jj, const int &kk) const { + return temperatureGrad_(ii, jj, kk); + } + vector3d TkeGrad(const int &ii, const int &jj, const int &kk) const { + return tkeGrad_(ii, jj, kk); + } + vector3d OmegaGrad(const int &ii, const int &jj, + const int &kk) const { + return omegaGrad_(ii, jj, kk); + } + + double Temperature(const int &ii, const int &jj, const int &kk) const { + return temperature_(ii, jj, kk); + } + double Viscosity(const int &ii, const int &jj, const int &kk) const { + return isViscous_ ? viscosity_(ii, jj, kk) : 0.0; + } + double EddyViscosity(const int &ii, const int &jj, const int &kk) const { + return isTurbulent_ ? eddyViscosity_(ii, jj, kk) : 0.0; + } + double F1(const int &ii, const int &jj, const int &kk) const { + return isTurbulent_ ? f1_(ii, jj, kk) : 0.0; + } + double F2(const int &ii, const int &jj, const int &kk) const { + return isTurbulent_ ? f2_(ii, jj, kk) : 0.0; + } + void CalcBlockTimeStep(const input &, const double &); void UpdateBlock(const input &, const idealGas &, const double &, const sutherland &, const multiArray3d &, @@ -252,11 +298,16 @@ class procBlock { const unique_ptr &, const int &, genArray &, resid &); - void CalcResidual(const sutherland &, const idealGas &, const input &, - const unique_ptr &, - multiArray3d &); + void CalcResidualNoSource(const sutherland &, const idealGas &, + const input &, + const unique_ptr &, + multiArray3d &); + void CalcSrcTerms(const sutherland &, const unique_ptr &, + const input &, multiArray3d &); void ResetResidWS(); + void ResetGradients(); + void ResetTurbVars(); void CleanResizeVecs(const int &, const int &, const int &); void AssignGhostCellsGeom(); @@ -276,15 +327,15 @@ class procBlock { const sutherland &, const unique_ptr &); - void CalcGradsI(const int &, const int &, const int &, const idealGas &, - const bool &, tensor &, vector3d &, - vector3d &, vector3d &) const; - void CalcGradsJ(const int &, const int &, const int &, const idealGas &, - const bool &, tensor &, vector3d &, - vector3d &, vector3d &) const; - void CalcGradsK(const int &, const int &, const int &, const idealGas &, - const bool &, tensor &, vector3d &, - vector3d &, vector3d &) const; + void CalcGradsI(const int &, const int &, const int &, + tensor &, vector3d &, vector3d &, + vector3d &) const; + void CalcGradsJ(const int &, const int &, const int &, + tensor &, vector3d &, vector3d &, + vector3d &) const; + void CalcGradsK(const int &, const int &, const int &, + tensor &, vector3d &, vector3d &, + vector3d &) const; void CalcWallDistance(const kdtree &); @@ -322,6 +373,8 @@ class procBlock { bool AtCorner(const int &, const int &, const int &, const bool &) const; bool AtEdge(const int &, const int &, const int &, const bool &, string &) const; + bool AtEdgeInclusive(const int &, const int &, const int &, const bool &, + string &) const; vector PutGeomSlice(const geomSlice &, interblock &, const int &, const int &); @@ -334,73 +387,34 @@ class procBlock { void SwapStateSlice(const interblock &, procBlock &); void SwapStateSliceMPI(const interblock &, const int &, const MPI_Datatype &); + void SwapTurbSlice(const interblock &, procBlock &); + void SwapTurbSliceMPI(const interblock &, const int &); void PackSendGeomMPI(const MPI_Datatype &, const MPI_Datatype &, const MPI_Datatype &) const; void RecvUnpackGeomMPI(const MPI_Datatype &, const MPI_Datatype &, const MPI_Datatype &); - void PackSendSolMPI(const MPI_Datatype &, const MPI_Datatype &) const; - void RecvUnpackSolMPI(const MPI_Datatype &, const MPI_Datatype &); - + void PackSendSolMPI(const MPI_Datatype &, const MPI_Datatype &, + const MPI_Datatype &, const MPI_Datatype &) const; + void RecvUnpackSolMPI(const MPI_Datatype &, const MPI_Datatype &, + const MPI_Datatype &, const MPI_Datatype &); + + void UpdateAuxillaryVariables(const idealGas &, const sutherland &, + const bool = true); + void UpdateUnlimTurbEddyVisc(const unique_ptr &, const bool &); + + double ProjC2CDist(const int &, const int &, const int &, + const string &) const; + // destructor ~procBlock() noexcept {} }; // function definitions -template -T FaceReconCentral(const T &, const T &, const vector3d &, - const vector3d &, const vector3d &); - template multiArray3d PadWithGhosts(const multiArray3d &, const int &); -tensor CalcVelGradGG(const vector3d &, const vector3d &, - const vector3d &, const vector3d &, - const vector3d &, const vector3d &, - const vector3d &, const vector3d &, - const vector3d &, const vector3d &, - const vector3d &, const vector3d &, - const double &); - -vector3d CalcScalarGradGG( - const double &, const double &, const double &, const double &, - const double &, const double &, const vector3d &, - const vector3d &, const vector3d &, - const vector3d &, const vector3d &, - const vector3d &, const double &); - -void SwapGeomSlice(interblock &, procBlock &, procBlock &); - -void GetBoundaryConditions(vector &, const input &, const idealGas &, - const sutherland &, const unique_ptr &, - vector &, const int &, - const MPI_Datatype &); - -vector> GetViscousFaceCenters(const vector &); -void CalcWallDistance(vector &, const kdtree &); - -vector> GetCopyConsVars(const vector &, - const idealGas &); - -void ExplicitUpdate(vector &, const input &, const idealGas &, - const double &, const sutherland &, - const vector> &, - const unique_ptr &, const int &, genArray &, - resid &); -double ImplicitUpdate(vector &, vector> &, - const input &, const idealGas &, const double &, - const sutherland &, - const vector> &, - const vector> &, - vector> &, - const unique_ptr &, - const int &, genArray &, resid &, - const vector &, const int &, - const MPI_Datatype &); - -void SwapImplicitUpdate(vector> &, - const vector &, const int &, - const MPI_Datatype &, const int &); + #endif diff --git a/slices.cpp b/slices.cpp index 0aa25a5..68eb907 100644 --- a/slices.cpp +++ b/slices.cpp @@ -24,20 +24,6 @@ using std::endl; using std::cerr; // constructors for geomSlice class -geomSlice::geomSlice() { - parBlock_ = 0; - - center_ = multiArray3d>(1, 1, 1); - fAreaI_ = multiArray3d>(1, 1, 1); - fAreaJ_ = fAreaI_; - fAreaK_ = fAreaI_; - fCenterI_ = multiArray3d>(1, 1, 1); - fCenterJ_ = fCenterI_; - fCenterK_ = fCenterI_; - - vol_ = multiArray3d(1, 1, 1); -} - // constructor -- initialize state vector with dummy variables geomSlice::geomSlice(const int &li, const int &lj, const int &lk, const int &pblk) { @@ -48,15 +34,15 @@ geomSlice::geomSlice(const int &li, const int &lj, const int &lk, parBlock_ = pblk; - center_ = multiArray3d>(li, lj, lk); - fAreaI_ = multiArray3d> (li + 1, lj, lk); - fAreaJ_ = multiArray3d> (li, lj + 1, lk); - fAreaK_ = multiArray3d> (li, lj, lk + 1); - fCenterI_ = multiArray3d> (li + 1, lj, lk); - fCenterJ_ = multiArray3d> (li, lj + 1, lk); - fCenterK_ = multiArray3d> (li, lj, lk + 1); + center_ = {li, lj, lk}; + fAreaI_ = {li + 1, lj, lk}; + fAreaJ_ = {li, lj + 1, lk}; + fAreaK_ = {li, lj, lk + 1}; + fCenterI_ = {li + 1, lj, lk}; + fCenterJ_ = {li, lj + 1, lk}; + fCenterK_ = {li, lj, lk + 1}; - vol_ = multiArray3d(li, lj, lk); + vol_ = {li, lj, lk}; } /* constructor to get a slice (portion) of the geometry of a procBlock. The @@ -86,14 +72,14 @@ geomSlice::geomSlice(const procBlock &blk, const int &is, const int &ie, parBlock_ = blk.ParentBlock(); // allocate size for vectors - center_ = multiArray3d>(numI, numJ, numK); - fAreaI_ = multiArray3d>(numI + 1, numJ, numK); - fAreaJ_ = multiArray3d>(numI, numJ + 1, numK); - fAreaK_ = multiArray3d>(numI, numJ, numK + 1); - fCenterI_ = multiArray3d>(numI + 1, numJ, numK); - fCenterJ_ = multiArray3d>(numI, numJ + 1, numK); - fCenterK_ = multiArray3d>(numI, numJ, numK + 1); - vol_ = multiArray3d(numI, numJ, numK); + center_ = {numI, numJ, numK}; + fAreaI_ = {numI + 1, numJ, numK}; + fAreaJ_ = {numI, numJ + 1, numK}; + fAreaK_ = {numI, numJ, numK + 1}; + fCenterI_ = {numI + 1, numJ, numK}; + fCenterJ_ = {numI, numJ + 1, numK}; + fCenterK_ = {numI, numJ, numK + 1}; + vol_ = {numI, numJ, numK}; // loop over all cells in slice and populate for (auto kk = 0; kk < vol_.NumK(); kk++) { diff --git a/slices.hpp b/slices.hpp index 4654d6d..ecd1552 100644 --- a/slices.hpp +++ b/slices.hpp @@ -52,8 +52,8 @@ class geomSlice { public: // constructors - geomSlice(); geomSlice(const int &, const int &, const int &, const int &); + geomSlice() : geomSlice(1, 1, 1, 0) {} geomSlice(const procBlock &, const int &, const int &, const int &, const int &, const int &, const int &, const bool = false, const bool = false, const bool = false); diff --git a/source.cpp b/source.cpp index 6d6d539..9e83ee5 100644 --- a/source.cpp +++ b/source.cpp @@ -22,7 +22,9 @@ #include "source.hpp" #include "turbulence.hpp" #include "primVars.hpp" -#include "gradients.hpp" +#include "vector3d.hpp" +#include "tensor.hpp" +#include "matrix.hpp" using std::cout; using std::endl; @@ -44,37 +46,35 @@ ostream &operator<<(ostream &os, const source &src) { } // Member function to calculate the source terms for the turbulence equations -double source::CalcTurbSrc(const unique_ptr &turb, - const primVars &state, const gradients &grads, - const sutherland &suth, const idealGas &eqnState, - const double &wallDist, const double &vol, - const int &ii, const int &jj, const int &kk) { +squareMatrix source::CalcTurbSrc(const unique_ptr &turb, + const primVars &state, + const tensor &velGrad, + const vector3d &tGrad, + const vector3d &tkeGrad, + const vector3d &omegaGrad, + const sutherland &suth, const double &vol, + const double &mut, const double &f1) { // turb -- turbulence model // state -- primative variables - // grads -- gradients + // velGrad -- velocity gradient + // tGrad -- temperature gradient + // tkeGrad -- tke gradient + // omegaGrad -- omega gradient // suth -- sutherland's law for viscosity - // eqnState -- equation of state - // wallDist -- distance to nearest viscous wall // vol -- cell volume - // ii -- cell i-location to calculate source terms at - // jj -- cell j-location to calculate source terms at - // kk -- cell k-location to calculate source terms at - - // get cell gradients - const auto vGrad = grads.VelGradCell(ii, jj, kk); - const auto kGrad = grads.TkeGradCell(ii, jj, kk); - const auto wGrad = grads.OmegaGradCell(ii, jj, kk); + // mut -- turbulent viscosity + // f1 -- first blending coefficient // calculate turbulent source terms auto ksrc = 0.0; auto wsrc = 0.0; - auto srcJacSpecRad = turb->CalcTurbSrc(state, vGrad, kGrad, wGrad, suth, - eqnState, wallDist, vol, ksrc, wsrc); + const auto srcJac = turb->CalcTurbSrc(state, velGrad, tkeGrad, omegaGrad, + suth, vol, mut, f1, ksrc, wsrc); // assign turbulent source terms data_[5] = ksrc; data_[6] = wsrc; - // return spectral radius of source jacobian - return srcJacSpecRad; + // return source jacobian + return srcJac; } diff --git a/source.hpp b/source.hpp index 26383f2..3989c95 100644 --- a/source.hpp +++ b/source.hpp @@ -28,6 +28,8 @@ #include #include #include "macros.hpp" +#include "vector3d.hpp" +#include "tensor.hpp" using std::vector; using std::string; @@ -41,8 +43,7 @@ using std::unique_ptr; class primVars; class turbModel; class sutherland; -class idealGas; -class gradients; +class squareMatrix; class source { double data_[NUMVARS]; // source variables at cell center @@ -68,10 +69,11 @@ class source { double SrcTke() const { return data_[5]; } double SrcOmg() const { return data_[6]; } - double CalcTurbSrc(const unique_ptr &, const primVars &, - const gradients &, const sutherland &, - const idealGas &, const double &, const double &, - const int &, const int &, const int &); + squareMatrix CalcTurbSrc(const unique_ptr &, const primVars &, + const tensor &, const vector3d &, + const vector3d &, const vector3d &, + const sutherland &, const double &, const double &, + const double &); inline source & operator+=(const source &); inline source & operator-=(const source &); diff --git a/tensor.hpp b/tensor.hpp index ef153c0..934a45f 100644 --- a/tensor.hpp +++ b/tensor.hpp @@ -31,7 +31,7 @@ #include // is_arithmetic #include "vector3d.hpp" -#define SIZE 9 +#define TENSORSIZE 9 using std::ostream; using std::endl; @@ -42,7 +42,12 @@ class tensor { static_assert(std::is_arithmetic::value, "tensor requires an arithmetic type!"); - T data_[SIZE]; + T data_[TENSORSIZE]; + + // private member functions + int GetLoc(const int &rr, const int &cc) const { + return cc + rr * this->Size(); + } public: // constructor @@ -65,6 +70,14 @@ class tensor { // member functions // operator overloads + T& operator()(const int &rr, const int &cc) { + return data_[this->GetLoc(rr, cc)]; + } + const T& operator()(const int &rr, const int &cc) const { + return data_[this->GetLoc(rr, cc)]; + } + + inline tensor & operator+=(const tensor &); inline tensor & operator-=(const tensor &); inline tensor & operator*=(const tensor &); @@ -128,7 +141,8 @@ class tensor { T DoubleDotTrans(const tensor &) const; void Identity(); void Zero(); - + int Size() const {return 3;} + // destructor ~tensor() noexcept {} }; @@ -136,7 +150,7 @@ class tensor { // operator overload for addition template tensor & tensor::operator+=(const tensor &ten) { - for (auto rr = 0; rr < SIZE; rr++) { + for (auto rr = 0; rr < TENSORSIZE; rr++) { data_[rr] += ten.data_[rr]; } return *this; @@ -145,7 +159,7 @@ tensor & tensor::operator+=(const tensor &ten) { // operator overload for subtraction with a scalar template tensor & tensor::operator-=(const tensor &ten) { - for (auto rr = 0; rr < SIZE; rr++) { + for (auto rr = 0; rr < TENSORSIZE; rr++) { data_[rr] -= ten.data_[rr]; } return *this; @@ -154,7 +168,7 @@ tensor & tensor::operator-=(const tensor &ten) { // operator overload for elementwise multiplication template tensor & tensor::operator*=(const tensor &ten) { - for (auto rr = 0; rr < SIZE; rr++) { + for (auto rr = 0; rr < TENSORSIZE; rr++) { data_[rr] *= ten.data_[rr]; } return *this; @@ -163,7 +177,7 @@ tensor & tensor::operator*=(const tensor &ten) { // operator overload for elementwise division template tensor & tensor::operator/=(const tensor &ten) { - for (auto rr = 0; rr < SIZE; rr++) { + for (auto rr = 0; rr < TENSORSIZE; rr++) { data_[rr] /= ten.data_[rr]; } return *this; @@ -233,7 +247,7 @@ inline const tensor operator+(const T &lhs, tensor rhs) { template inline const tensor operator-(const T &lhs, tensor rhs) { - for (auto rr = 0; rr < SIZE; rr++) { + for (auto rr = 0; rr < TENSORSIZE; rr++) { rhs.data_[rr] = lhs - rhs.data_[rr]; } return rhs; @@ -246,47 +260,24 @@ inline const tensor operator*(const T &lhs, tensor rhs) { template inline const tensor operator/(const T &lhs, tensor rhs) { - for (auto rr = 0; rr < SIZE; rr++) { + for (auto rr = 0; rr < TENSORSIZE; rr++) { rhs.data_[rr] = lhs / rhs.data_[rr]; } return rhs; } // function for matrix multiplication +// using more cache efficient method template tensor tensor::MatMult(const tensor &v2) const { tensor temp; - - temp.data_[0] = data_[0] * v2.data_[0] + - data_[1] * v2.data_[3] + - data_[2] * v2.data_[6]; - temp.data_[1] = data_[0] * v2.data_[1] + - data_[1] * v2.data_[4] + - data_[2] * v2.data_[7]; - temp.data_[2] = data_[0] * v2.data_[2] + - data_[1] * v2.data_[5] + - data_[2] * v2.data_[8]; - - temp.data_[3] = data_[3] * v2.data_[0] + - data_[4] * v2.data_[3] + - data_[5] * v2.data_[6]; - temp.data_[4] = data_[3] * v2.data_[1] + - data_[4] * v2.data_[4] + - data_[5] * v2.data_[7]; - temp.data_[5] = data_[3] * v2.data_[2] + - data_[4] * v2.data_[5] + - data_[5] * v2.data_[8]; - - temp.data_[6] = data_[6] * v2.data_[0] + - data_[7] * v2.data_[3] + - data_[8] * v2.data_[6]; - temp.data_[7] = data_[6] * v2.data_[1] + - data_[7] * v2.data_[4] + - data_[8] * v2.data_[7]; - temp.data_[8] = data_[6] * v2.data_[2] + - data_[7] * v2.data_[5] + - data_[8] * v2.data_[8]; - + for (auto cc = 0; cc < v2.Size(); cc++) { + for (auto rr = 0; rr < v2.Size(); rr++) { + for (auto ii = 0; ii < v2.Size(); ii++) { + temp(rr, ii) += (*this)(rr, cc) * v2(cc, ii); + } + } + } return temp; } diff --git a/testCases/multiblockCylinder/multiblockCylinder.inp b/testCases/multiblockCylinder/multiblockCylinder.inp index 0153984..d4ccd4c 100644 --- a/testCases/multiblockCylinder/multiblockCylinder.inp +++ b/testCases/multiblockCylinder/multiblockCylinder.inp @@ -12,6 +12,7 @@ faceReconstruction: thirdOrder limiter: none iterations: 5000 outputFrequency: 1000 +outputVariables: density vel_x vel_y vel_z pressure mach stagnationInlet: 1 107826.8 293.18 1.0 0.0 0.0 pressureOutlet: 2 101300.0 diff --git a/testCases/subsonicCylinder/subsonicCylinder.inp b/testCases/subsonicCylinder/subsonicCylinder.inp index 2e8c1a5..945d286 100644 --- a/testCases/subsonicCylinder/subsonicCylinder.inp +++ b/testCases/subsonicCylinder/subsonicCylinder.inp @@ -1,7 +1,7 @@ #This is the input file -# + gridName: subsonicCylinder -# + #solver parameters equationSet: euler timeIntegration: implicitEuler @@ -11,19 +11,20 @@ faceReconstruction: thirdOrder limiter: none iterations: 5000 outputFrequency: 1000 -# +outputVariables: density vel_x vel_y vel_z pressure mach + stagnationInlet: 1 102010.0 288.58 1.0 0.0 0.0 pressureOutlet: 2 101300.0 -# + #reference conditions pressureRef: 101300.0 densityRef: 1.2256 temperatureRef: 288.0 velocity: 34.017, 0.0, 0.0 -# + matrixSolver: lusgs matrixRelaxation: 1.0 -# + #---------------------------------------------------------------------------# #Boundary Conditions # bc imin imax jmin jmax kmin kmax tag diff --git a/testCases/supersonicWedge/supersonicWedge.inp b/testCases/supersonicWedge/supersonicWedge.inp index d685c61..351c06f 100644 --- a/testCases/supersonicWedge/supersonicWedge.inp +++ b/testCases/supersonicWedge/supersonicWedge.inp @@ -1,7 +1,7 @@ #This is the input file -# + gridName: supersonicWedge -# + #solver parameters equationSet: euler timeIntegration: explicitEuler @@ -11,13 +11,14 @@ faceReconstruction: thirdOrder limiter: vanAlbada iterations: 5000 outputFrequency: 1000 -# +outputVariables: density vel_x vel_y vel_z pressure mach + #reference conditions pressureRef: 101300.0 densityRef: 1.2256 temperatureRef: 288.0 velocity: 852.4, 0.0, 0.0 -# + #---------------------------------------------------------------------------# #Boundary Conditions # bc imin imax jmin jmax kmin kmax tag diff --git a/testCases/transonicBump/transonicBump.inp b/testCases/transonicBump/transonicBump.inp index 9e20a87..6cdc2ed 100644 --- a/testCases/transonicBump/transonicBump.inp +++ b/testCases/transonicBump/transonicBump.inp @@ -1,7 +1,7 @@ #This is the input file -# + gridName: transonicBump -# + #solver parameters equationSet: euler timeIntegration: implicitEuler @@ -12,13 +12,14 @@ faceReconstruction: upwind limiter: vanAlbada iterations: 2000 outputFrequency: 500 -# +outputVariables: density vel_x vel_y vel_z pressure mach + #reference conditions pressureRef: 101300.0 densityRef: 1.2256 temperatureRef: 288.0 velocity: 238.0, 0.0, 0.0 -# + matrixSolver: lusgs matrixRelaxation: 1.0 #---------------------------------------------------------------------------# diff --git a/testCases/turbFlatPlate/turbFlatPlate.inp b/testCases/turbFlatPlate/turbFlatPlate.inp index 8ebf849..b6a6a87 100644 --- a/testCases/turbFlatPlate/turbFlatPlate.inp +++ b/testCases/turbFlatPlate/turbFlatPlate.inp @@ -15,6 +15,7 @@ faceReconstruction: thirdOrder limiter: vanAlbada iterations: 25000 outputFrequency: 1000 +outputVariables: density vel_x vel_y vel_z pressure mach tke sdr viscosityRatio wallDistance stagnationInlet: 1 117662.9 302.4 1.0 0.0 0.0 pressureOutlet: 2 114426.9 diff --git a/testCases/viscousFlatPlate/viscousFlatPlate.inp b/testCases/viscousFlatPlate/viscousFlatPlate.inp index b122f82..9bd130c 100644 --- a/testCases/viscousFlatPlate/viscousFlatPlate.inp +++ b/testCases/viscousFlatPlate/viscousFlatPlate.inp @@ -1,7 +1,7 @@ #This is the input file -# + gridName: viscousFlatPlate -# + #solver parameters equationSet: navierStokes timeIntegration: implicitEuler @@ -11,16 +11,17 @@ faceReconstruction: thirdOrder limiter: none iterations: 25000 outputFrequency: 1000 -# +outputVariables: density vel_x vel_y vel_z pressure mach velGrad_ux velGrad_uy velGrad_uz + #reference conditions pressureRef: 101300.0 densityRef: 1.2256 temperatureRef: 288.0 velocity: 68.0, 0.0, 0.0 -# + matrixSolver: lusgs matrixRelaxation: 1.0 -# + #---------------------------------------------------------------------------# #Boundary Conditions # bc imin imax jmin jmax kmin kmax tag diff --git a/turbulence.cpp b/turbulence.cpp index fe705c1..dfd029e 100644 --- a/turbulence.cpp +++ b/turbulence.cpp @@ -20,6 +20,7 @@ #include "turbulence.hpp" #include "primVars.hpp" // primVars #include "eos.hpp" // sutherland +#include "matrix.hpp" // squareMatrix using std::cout; using std::endl; @@ -106,23 +107,28 @@ double turbModel::CrossDiffusion(const primVars &state, } // member function to calculate the spectral radius of the turbulence equations -double turbModel::SpectralRadius(const primVars &state, - const unitVec3dMag &fAreaL, - const unitVec3dMag &fAreaR, - const idealGas &eos, const sutherland &suth, - const double &vol, const bool &addSrc) const { +double turbModel::CellSpectralRadius(const primVars &state, + const unitVec3dMag &fAreaL, + const unitVec3dMag &fAreaR, + const double &mu, const sutherland &suth, + const double &vol, const double &mut, + const double &f1, + const bool &addSrc) const { // state -- primative variables // fAreaL -- area at left face // fAreaR -- area at right face - // eos -- equation of state + // mu -- laminar viscosity // suth -- sutherland's law for viscosity // vol -- cell volume + // mut -- turbulent viscosity + // f1 -- first blending coefficient // addSrc -- flag to determine if source jacobian spectral radius should be // included - auto specRad = this->InviscidSpecRad(state, fAreaL, fAreaR); + auto specRad = this->InviscidCellSpecRad(state, fAreaL, fAreaR); // factor of 2 because viscous spectral radius is not halved (Blazek 6.53) - specRad += 2.0 * this->ViscSpecRad(state, fAreaL, fAreaR, eos, suth, vol); + specRad += 2.0 * this->ViscCellSpecRad(state, fAreaL, fAreaR, mu, suth, vol, + mut, f1); if (addSrc) { // minus sign because source terms are on RHS specRad -= this->SrcSpecRad(state, suth, vol); @@ -131,12 +137,77 @@ double turbModel::SpectralRadius(const primVars &state, return specRad; } +double turbModel::FaceSpectralRadius(const primVars &state, + const unitVec3dMag &fArea, + const double &mu, const sutherland &suth, + const double &dist, const double &mut, + const double &f1, + const bool &positive) const { + // state -- primative variables + // fArea -- face area + // mu -- laminar viscosity + // suth -- sutherland's law for viscosity + // dist -- distance from cell center to cell center + // mut -- turbulent viscosity + // f1 -- first blending coefficient + // positive -- flag to add or subtract inviscid dissipation + + auto specRad = this->InviscidFaceSpecRad(state, fArea, positive); + specRad += this->ViscFaceSpecRad(state, fArea, mu, suth, dist, mut, f1); + return specRad; +} + + +// member function to calculate inviscid flux jacobian +// v = vel (dot) area +// df_dq = [v +/- |v| 0 ] +// [ 0 v +/- |v|] +squareMatrix turbModel::InviscidJacobian(const primVars &state, + const unitVec3dMag &fArea, + const bool &positive) const { + // state -- primative variables at face + // fArea -- face area + // positive -- flag to determine whether to add/subtract dissipation + + return positive ? 0.5 * (this->InviscidConvJacobian(state, fArea) + + this->InviscidDissJacobian(state, fArea)) : + 0.5 * (this->InviscidConvJacobian(state, fArea) - + this->InviscidDissJacobian(state, fArea)); +} + +squareMatrix turbModel::InviscidConvJacobian( + const primVars &state, const unitVec3dMag &fArea) const { + // state -- primative variables at face + // fArea -- face area + + const auto velNorm = state.Velocity().DotProd(fArea.UnitVector()); + const auto diag = velNorm * fArea.Mag(); + squareMatrix jacobian(2); + jacobian(0, 0) = diag; + jacobian(1, 1) = diag; + return jacobian; +} + +squareMatrix turbModel::InviscidDissJacobian( + const primVars &state, const unitVec3dMag &fArea) const { + // state -- primative variables at face + // fArea -- face area + + const auto velNorm = state.Velocity().DotProd(fArea.UnitVector()); + const auto diag = fabs(velNorm) * fArea.Mag(); + squareMatrix jacobian(2); + jacobian(0, 0) = diag; + jacobian(1, 1) = diag; + return jacobian; +} + + // member function to calculate inviscid spectral radius // df_dq = [vel (dot) area 0 // 0 vel (dot) area] -double turbModel::InviscidSpecRad(const primVars &state, - const unitVec3dMag &fAreaL, - const unitVec3dMag &fAreaR) const { +double turbModel::InviscidCellSpecRad(const primVars &state, + const unitVec3dMag &fAreaL, + const unitVec3dMag &fAreaR) const { // state -- primative variables // fAreaL -- face area for left face // fAreaR -- face area for right face @@ -144,9 +215,42 @@ double turbModel::InviscidSpecRad(const primVars &state, auto normAvg = (0.5 * (fAreaL.UnitVector() + fAreaR.UnitVector())).Normalize(); auto fMag = 0.5 * (fAreaL.Mag() + fAreaR.Mag()); - return state.Velocity().DotProd(normAvg) * fMag; + return fabs(state.Velocity().DotProd(normAvg)) * fMag; } +double turbModel::InviscidFaceSpecRad(const primVars &state, + const unitVec3dMag &fArea, + const bool &positive) const { + // state -- primative variables + // fArea -- face area + // positive -- add or subtract dissipation term + + const auto velNorm = state.Velocity().DotProd(fArea.UnitVector()); + // returning absolute value because it is expected that spectral radius is + // positive + return positive ? 0.5 * fArea.Mag() * fabs(velNorm + fabs(velNorm)) : + 0.5 * fArea.Mag() * fabs(velNorm - fabs(velNorm)); +} + +// member function to calculate viscous flux jacobian for models with no +// viscous contribution +squareMatrix turbModel::ViscousJacobian(const primVars &state, + const unitVec3dMag &fArea, + const double &mu, + const sutherland &suth, + const double &dist, + const double &mut, + const double &f1) const { + // state -- primative variables + // fAreaL -- face area for left face + // mu -- laminar viscosity + // suth -- sutherland's law for viscosity + // dist -- distance from cell center to cell center across face + // mut -- turbulent viscosity + // f1 -- first blending coefficient + + return squareMatrix(); +} // ------------------------------------------------------------------------- // member functions for the turbNone class @@ -157,19 +261,51 @@ void turbNone::Print() const { } // member function to calculate turbulence source terms -double turbNone::CalcTurbSrc(const primVars &state, - const tensor &velGrad, - const vector3d &kGrad, - const vector3d &wGrad, - const sutherland &suth, const idealGas &eos, - const double &wallDist, const double &vol, - double &ksrc, double &wsrc) const { +squareMatrix turbNone::CalcTurbSrc(const primVars &state, + const tensor &velGrad, + const vector3d &kGrad, + const vector3d &wGrad, + const sutherland &suth, const double &vol, + const double &turbVisc, const double &f1, + double &ksrc, double &wsrc) const { // set k and omega source terms to zero ksrc = 0.0; wsrc = 0.0; // return source jacobian spectral radius - return this->SrcSpecRad(state, suth, vol); + return this->TurbSrcJac(state, 0.0, suth, vol); +} + +squareMatrix turbNone::TurbSrcJac(const primVars &state, const double &beta, + const sutherland &suth, + const double &vol) const { + return squareMatrix(); +} + +squareMatrix turbNone::InviscidJacobian(const primVars &state, + const unitVec3dMag &fArea, + const bool &positive) const { + // state -- primative variables at face + // fArea -- face area + // positive -- flag to determine whether to add/subtract spectral radius + + return squareMatrix(); +} + +squareMatrix turbNone::InviscidConvJacobian( + const primVars &state, const unitVec3dMag &fArea) const { + // state -- primative variables at face + // fArea -- face area + + return squareMatrix(); +} + +squareMatrix turbNone::InviscidDissJacobian( + const primVars &state, const unitVec3dMag &fArea) const { + // state -- primative variables at face + // fArea -- face area + + return squareMatrix(); } // --------------------------------------------------------------------- @@ -269,21 +405,23 @@ double turbKWWilcox::OmegaTilda(const primVars &state, } // member function to calculate turbulence source terms and return source -// spectral radius -double turbKWWilcox::CalcTurbSrc(const primVars &state, - const tensor &velGrad, - const vector3d &kGrad, - const vector3d &wGrad, - const sutherland &suth, const idealGas &eos, - const double &wallDist, const double &vol, - double &ksrc, double &wsrc) const { +// jacobian +squareMatrix turbKWWilcox::CalcTurbSrc(const primVars &state, + const tensor &velGrad, + const vector3d &kGrad, + const vector3d &wGrad, + const sutherland &suth, + const double &vol, + const double &mut, const double &f1, + double &ksrc, double &wsrc) const { // state -- primative variables // velGrad -- velocity gradient // kGrad -- tke gradient // wGrad -- omega gradient // suth -- sutherland's law - // eos -- equation of state - // wallDist -- distance to nearest viscous wall + // vol -- cell volume + // mut -- turbulent viscosity + // f1 -- first blending coefficient // ksrc -- source term for tke equation // wsrc -- source term for omega equation @@ -292,16 +430,18 @@ double turbKWWilcox::CalcTurbSrc(const primVars &state, this->TkeDestruction(state); // calculate omega destruction - const auto omgDest = suth.InvNondimScaling() * - this->Beta(state, velGrad, suth) * this->OmegaDestruction(state); + const auto beta = this->Beta(state, velGrad, suth); + const auto omgDest = suth.InvNondimScaling() * beta * + this->OmegaDestruction(state); // calculate tke production - const auto mut = this->EddyVisc(state, velGrad, suth, 0.0); - const auto tkeProd = suth.NondimScaling() * + auto tkeProd = suth.NondimScaling() * this->ReynoldsStressDDotVelGrad(state, velGrad, suth, mut); + tkeProd = max(tkeProd, 0.0); // calculate omega production - const auto omgProd = gamma_ * state.Omega() / state.Tke() * tkeProd; + auto omgProd = gamma_ * state.Omega() / state.Tke() * tkeProd; + omgProd = max(omgProd, 0.0); // calculate omega cross diffusion const auto omgCd = suth.NondimScaling() * this->SigmaD(kGrad, wGrad) * @@ -311,41 +451,40 @@ double turbKWWilcox::CalcTurbSrc(const primVars &state, ksrc = tkeProd - tkeDest; wsrc = omgProd - omgDest + omgCd; - // return spectral radius of source jacobian - return this->SrcSpecRad(state, suth, vol); -} - -// member function to calculate the eddy viscosity, and the molecular diffusion -// coefficients. The eddy viscosity is used in the viscous flux calculation -// for the Navier-Stokes equations, and the molecular diffusion coefficients are -// used in the viscous flux calculation for the turbulence equations -double turbKWWilcox::EddyViscAndMolecDiffCoeff(const primVars &state, - const tensor &velGrad, - const vector3d &kGrad, - const vector3d &wGrad, - const sutherland &suth, - const idealGas &eos, - const double &wallDist, - double &sigmaK, - double &sigmaW) const { + // return source jacobian + return this->TurbSrcJac(state, beta, suth, vol); +} + +// member function to calculate the eddy viscosity, and the blending +// coefficients. +void turbKWWilcox::EddyViscAndBlending(const primVars &state, + const tensor &velGrad, + const vector3d &kGrad, + const vector3d &wGrad, + const double &mu, + const double &wallDist, + const sutherland &suth, + double &mut, double &f1, + double &f2) const { // state -- primative variables // velGrad -- velocity gradient // kGrad -- tke gradient // wGrad -- omega gradient - // suth -- sutherland's law for viscosity - // eos -- equation of state + // mu -- laminar viscosity // walldist -- distance to nearest viscous wall - // sigmaK -- molecular diffusion coefficient for tke equation - // sigmaW -- molecular diffusion coefficient for omega equation + // suth -- sutherland's law for viscosity + // mut -- turbulent eddy viscosity + // f1 -- first blending coefficient + // f2 -- second blending coefficient - // calculate blended coefficients - sigmaK = sigmaStar_; - sigmaW = sigma_; + f1 = 1.0; + f2 = 0.0; - // return eddy viscosity, scaled for nondimensional equations - return this->EddyVisc(state, velGrad, suth, 0.0) * suth.NondimScaling(); + // return eddy viscosity + mut = this->EddyVisc(state, velGrad, suth, f2); } + /* member function to calculate the spectral radius of the source jacobian Source jacobian from Wilcox used. @@ -366,28 +505,95 @@ double turbKWWilcox::SrcSpecRad(const primVars &state, return -2.0 * betaStar_ * state.Omega() * vol * suth.InvNondimScaling(); } +squareMatrix turbKWWilcox::TurbSrcJac(const primVars &state, + const double &beta, + const sutherland &suth, + const double &vol) const { + // state -- primative variables + // beta -- destruction coefficient for omega equation + // suth -- sutherland's law for viscosity + // vol -- cell volume + + squareMatrix jac(2); + jac(0, 0) = -2.0 * betaStar_ * state.Omega() * vol * suth.InvNondimScaling(); + jac(1, 1) = -2.0 * beta * state.Omega() * vol * suth.InvNondimScaling(); + + // return jacobian scaled for nondimensional equations + return jac; +} + +// member function to calculate viscous flux jacobian +// dfv_dq = [ (nu + sigmaStar * nut) / dist 0 ] +// [ 0 (nu + sigma * nut) / dist] +squareMatrix turbKWWilcox::ViscousJacobian(const primVars &state, + const unitVec3dMag &fArea, + const double &mu, + const sutherland &suth, + const double &dist, + const double &mut, + const double &f1) const { + // state -- primative variables + // fAreaL -- face area for left face + // mu -- laminar viscosity + // suth -- sutherland's law for viscosity + // dist -- distance from cell center to cell center across face + // mut -- turbulent viscosity + // f1 -- first blending coefficient + + squareMatrix jacobian(2); + // Wilcox method uses unlimited eddy viscosity + jacobian(0, 0) = fArea.Mag() * suth.NondimScaling() / (dist * state.Rho()) * + (mu + this->SigmaK(f1) * this->EddyViscNoLim(state)); + jacobian(1, 1) = fArea.Mag() * suth.NondimScaling() / (dist * state.Rho()) * + (mu + this->SigmaW(f1) * this->EddyViscNoLim(state)); + + return jacobian; +} + // member function to calculate viscous spectral radius // dfv_dq = [ (area / vol) * (nu + sigmaStar * nut) 0 // 0 (area / vol) * (nu + sigma * nut)] -double turbKWWilcox::ViscSpecRad(const primVars &state, - const unitVec3dMag &fAreaL, - const unitVec3dMag &fAreaR, - const idealGas &eos, const sutherland &suth, - const double &vol) const { +double turbKWWilcox::ViscCellSpecRad(const primVars &state, + const unitVec3dMag &fAreaL, + const unitVec3dMag &fAreaR, + const double &mu, const sutherland &suth, + const double &vol, const double &mut, + const double &f1) const { // state -- primative variables // fAreaL -- face area for left face // fAreaR -- face area for right face - // eos -- equation of state + // mu -- laminar viscosity // suth -- sutherland's law for viscosity // vol -- cell volume + // mut -- turbulent viscosity + // f1 -- first blending coefficient const auto fMag = 0.5 * (fAreaL.Mag() + fAreaR.Mag()); + // Wilcox method uses unlimited eddy viscosity return suth.NondimScaling() * fMag * fMag / (vol * state.Rho()) * - (suth.Viscosity(state.Temperature(eos)) + - sigmaStar_ * this->EddyViscNoLim(state)); + (mu + this->SigmaK(f1) * this->EddyViscNoLim(state)); +} + +double turbKWWilcox::ViscFaceSpecRad(const primVars &state, + const unitVec3dMag &fArea, + const double &mu, const sutherland &suth, + const double &dist, const double &mut, + const double &f1) const { + // state -- primative variables + // fArea -- face area + // mu -- laminar viscosity + // suth -- sutherland's law for viscosity + // dist -- distance from cell center to cell center + // mut -- turbulent viscosity + // f1 -- first blending coefficient + + // Wilcox method uses unlimited eddy viscosity + return suth.NondimScaling() * fArea.Mag() / (dist * state.Rho()) * + (mu + this->SigmaK(f1) * this->EddyViscNoLim(state)); } + // member function to print out turbulence variables void turbKWWilcox::Print() const { cout << "Eddy Viscosity Method: " << this->EddyViscMethod() << endl; @@ -455,51 +661,45 @@ double turbKWSst::BlendedCoeff(const double &coeff1, const double &coeff2, double turbKWSst::Alpha1(const primVars &state, const sutherland &suth, const double &wallDist) const { return suth.NondimScaling() * sqrt(state.Tke()) / - (betaStar_ * state.Omega() * wallDist); + (betaStar_ * state.Omega() * (wallDist + EPS)); } // member function to calculate blending term double turbKWSst::Alpha2(const primVars &state, const sutherland &suth, - const idealGas &eos, const double &wallDist) const { + const double &mu, const double &wallDist) const { return suth.NondimScaling() * suth.NondimScaling() * - 500.0 * suth.Viscosity(state.Temperature(eos)) / - (wallDist * wallDist * state.Rho() * state.Omega()); + 500.0 * mu / ((wallDist + EPS) * (wallDist + EPS) * state.Rho() * + state.Omega()); } // member function to calculate blending term double turbKWSst::Alpha3(const primVars &state, const double &wallDist, const double &cdkw) const { return 4.0 * state.Rho() * sigmaW2_ * state.Tke() / - (cdkw * wallDist * wallDist); -} - -// member function to calculate turbulence source terms and source spectral -// radius -double turbKWSst::CalcTurbSrc(const primVars &state, - const tensor &velGrad, - const vector3d &kGrad, - const vector3d &wGrad, - const sutherland &suth, const idealGas &eos, - const double &wallDist, const double &vol, - double &ksrc, double &wsrc) const { + (cdkw * (wallDist + EPS) * (wallDist + EPS)); +} + +// member function to calculate turbulence source terms and source jacobian +squareMatrix turbKWSst::CalcTurbSrc(const primVars &state, + const tensor &velGrad, + const vector3d &kGrad, + const vector3d &wGrad, + const sutherland &suth, const double &vol, + const double &mut, const double &f1, + double &ksrc, double &wsrc) const { // state -- primative variables // velGrad -- velocity gradient // kGrad -- tke gradient // wGrad -- omega gradient // suth -- sutherland's law - // eos -- equation of state - // wallDist -- distance to nearest viscous wall // vol -- cell volume + // mut -- turbulent viscosity + // f1 -- first blending coefficient // ksrc -- source term for tke equation // wsrc -- source term for omega equation - // calculate blending functions - const auto alpha1 = this->Alpha1(state, suth, wallDist); - const auto alpha2 = this->Alpha2(state, suth, eos, wallDist); + // calculate cross diffusion coefficient const auto cdkw = this->CDkw(state, kGrad, wGrad); - const auto alpha3 = this->Alpha3(state, wallDist, cdkw); - const auto f1 = this->F1(alpha1, alpha2, alpha3); - const auto f2 = this->F2(alpha1, alpha2); // calculate blended coefficients const auto gamma = this->BlendedCoeff(gamma1_, gamma2_, f1); @@ -514,14 +714,14 @@ double turbKWSst::CalcTurbSrc(const primVars &state, this->OmegaDestruction(state); // calculate tke production - const auto mut = this->EddyVisc(state, velGrad, suth, f2); - const auto tkeProd = - min(suth.NondimScaling() * - this->ReynoldsStressDDotVelGrad(state, velGrad, suth, mut), - kProd2Dest_ * tkeDest); + auto tkeProd = min(suth.NondimScaling() * + this->ReynoldsStressDDotVelGrad(state, velGrad, suth, mut), + kProd2Dest_ * tkeDest); + tkeProd = max(tkeProd, 0.0); // calculate omega production - const auto omgProd = gamma * state.Rho() / mut * tkeProd; + auto omgProd = gamma * state.Rho() / mut * tkeProd; + omgProd = max(omgProd, 0.0); // calculate omega cross diffusion // Using CDkw instead of whole cross diffusion term @@ -533,48 +733,44 @@ double turbKWSst::CalcTurbSrc(const primVars &state, wsrc = omgProd - omgDest + omgCd; // return spectral radius of source jacobian - return this->SrcSpecRad(state, suth, vol); -} - -// member function to calculate the eddy viscosity, and the molecular diffusion -// coefficients. The eddy viscosity is used in the viscous flux calculation -// for the Navier-Stokes equations, and the molecular diffusion coefficients are -// used in the viscous flux calculation for the turbulence equations -double turbKWSst::EddyViscAndMolecDiffCoeff(const primVars &state, - const tensor &velGrad, - const vector3d &kGrad, - const vector3d &wGrad, - const sutherland &suth, - const idealGas &eos, - const double &wallDist, - double &sigmaK, - double &sigmaW) const { + return this->TurbSrcJac(state, beta, suth, vol); +} + +// member function to calculate the eddy viscosity, and the blending +// coefficients. +void turbKWSst::EddyViscAndBlending(const primVars &state, + const tensor &velGrad, + const vector3d &kGrad, + const vector3d &wGrad, + const double &mu, + const double &wallDist, + const sutherland &suth, + double &mut, double &f1, + double &f2) const { // state -- primative variables // velGrad -- velocity gradient // kGrad -- tke gradient // wGrad -- omega gradient - // suth -- sutherland's law for viscosity - // eos -- equation of state + // mu -- laminar viscosity // walldist -- distance to nearest viscous wall - // sigmaK -- molecular diffusion coefficient for tke equation - // sigmaW -- molecular diffusion coefficient for omega equation + // suth -- sutherland's law for viscosity + // mut -- turbulent eddy viscosity + // f1 -- first blending coefficient + // f2 -- second blending coefficient // calculate blending functions const auto alpha1 = this->Alpha1(state, suth, wallDist); - const auto alpha2 = this->Alpha2(state, suth, eos, wallDist); + const auto alpha2 = this->Alpha2(state, suth, mu, wallDist); const auto cdkw = this->CDkw(state, kGrad, wGrad); const auto alpha3 = this->Alpha3(state, wallDist, cdkw); - const auto f1 = this->F1(alpha1, alpha2, alpha3); - const auto f2 = this->F2(alpha1, alpha2); - - // calculate blended coefficients - sigmaK = this->BlendedCoeff(sigmaK1_, sigmaK2_, f1); - sigmaW = this->BlendedCoeff(sigmaW1_, sigmaW2_, f1); + f1 = this->F1(alpha1, alpha2, alpha3); + f2 = this->F2(alpha1, alpha2); - // return limited eddy viscosity scaled for nondimensional equations - return this->EddyVisc(state, velGrad, suth, f2) * suth.NondimScaling(); + // return limited eddy viscosity + mut = this->EddyVisc(state, velGrad, suth, f2); } + /* member function to calculate the spectral radius of the source jacobian Source jacobian from Wilcox used. @@ -594,29 +790,88 @@ double turbKWSst::SrcSpecRad(const primVars &state, return -2.0 * betaStar_ * state.Omega() * vol * suth.InvNondimScaling(); } +squareMatrix turbKWSst::TurbSrcJac(const primVars &state, + const double &beta, + const sutherland &suth, + const double &vol) const { + // state -- primative variables + // beta -- destruction coefficient for omega equation + // suth -- sutherland's law for viscosity + // vol -- cell volume + + squareMatrix jac(2); + jac(0, 0) = -2.0 * betaStar_ * state.Omega() * vol * suth.InvNondimScaling(); + jac(1, 1) = -2.0 * beta * state.Omega() * vol * suth.InvNondimScaling(); + + // return jacobian scaled for nondimensional equations + return jac; +} + +// member function to calculate viscous flux jacobian +// dfv_dq = [ (nu + sigmaStar * nut) / dist 0 ] +// [ 0 (nu + sigma * nut) / dist] +squareMatrix turbKWSst::ViscousJacobian(const primVars &state, + const unitVec3dMag &fArea, + const double &mu, + const sutherland &suth, + const double &dist, const double &mut, + const double &f1) const { + // state -- primative variables + // fArea -- face area + // mu -- laminar viscosity + // suth -- sutherland's law for viscosity + // dist -- distance from cell center to cell center across face + // mut -- turbulent viscosity + // f1 -- first blending coefficient + + squareMatrix jacobian(2); + jacobian(0, 0) = fArea.Mag() * suth.NondimScaling() / (dist * state.Rho()) * + (mu + this->SigmaK(f1) * mut); + jacobian(1, 1) = fArea.Mag() * suth.NondimScaling() / (dist * state.Rho()) * + (mu + this->SigmaW(f1) * mut); + + return jacobian; +} // member function to calculate viscous spectral radius // dfv_dq = [ (area / vol) * (nu + sigmaStar * nut) 0 // 0 (area / vol) * (nu + sigma * nut)] -double turbKWSst::ViscSpecRad(const primVars &state, - const unitVec3dMag &fAreaL, - const unitVec3dMag &fAreaR, - const idealGas &eos, const sutherland &suth, - const double &vol) const { +double turbKWSst::ViscCellSpecRad(const primVars &state, + const unitVec3dMag &fAreaL, + const unitVec3dMag &fAreaR, + const double &mu, const sutherland &suth, + const double &vol, const double &mut, + const double &f1) const { // state -- primative variables // fAreaL -- face area for left face // fAreaR -- face area for right face - // eos -- equation of state + // mu -- laminar viscosity // suth -- sutherland's law for viscosity // vol -- cell volume + // mut -- turbulent viscosity + // f1 -- first blending coefficient const auto fMag = 0.5 * (fAreaL.Mag() + fAreaR.Mag()); - // should be blended sigmaK, but using largest value - const auto coeff = 1.0; return suth.NondimScaling() * fMag * fMag / (vol * state.Rho()) * - (suth.Viscosity(state.Temperature(eos)) + - coeff * this->EddyViscNoLim(state)); + (mu + this->SigmaK(f1) * mut); +} + +double turbKWSst::ViscFaceSpecRad(const primVars &state, + const unitVec3dMag &fArea, + const double &mu, const sutherland &suth, + const double &dist, const double &mut, + const double &f1) const { + // state -- primative variables + // fArea -- face area + // mu -- laminar viscosity + // suth -- sutherland's law for viscosity + // dist -- distance from cell center to cell center + // mut -- turbulent viscosity + // f1 -- first blending coefficient + + return suth.NondimScaling() * fArea.Mag() / (dist * state.Rho()) * + (mu + this->SigmaK(f1) * mut); } // member function to print out turbulence variables diff --git a/turbulence.hpp b/turbulence.hpp index 8e8c15b..0d47014 100644 --- a/turbulence.hpp +++ b/turbulence.hpp @@ -34,6 +34,7 @@ using std::string; class primVars; class sutherland; class idealGas; +class squareMatrix; class turbModel { const string eddyViscMethod_; @@ -44,8 +45,8 @@ class turbModel { explicit turbModel(const string &meth) : eddyViscMethod_(meth) {} // move constructor and assignment operator - turbModel(turbModel&&) noexcept = default; - turbModel& operator=(turbModel&&) noexcept = default; + turbModel(turbModel&&) = default; + turbModel& operator=(turbModel&&) = default; // copy constructor and assignment operator turbModel(const turbModel&) = default; @@ -57,8 +58,9 @@ class turbModel { virtual double TurbPrandtlNumber() const {return 0.9;} virtual double TkeMin() const {return 1.0e-20;} virtual double OmegaMin() const {return 1.0e-20;} - virtual double SigmaK() const {return 0.0;} - virtual double SigmaW() const {return 0.0;} + virtual double SigmaK(const double &f1) const {return 0.0;} + virtual double SigmaW(const double &f1) const {return 0.0;} + virtual bool UseUnlimitedEddyVisc() const {return false;} virtual double EddyVisc(const primVars &state, const tensor &vGrad, const sutherland &suth, @@ -67,14 +69,36 @@ class turbModel { virtual double SrcSpecRad(const primVars &state, const sutherland &suth, const double &vol) const {return 0.0;} - virtual double InviscidSpecRad(const primVars &state, + virtual squareMatrix InviscidJacobian(const primVars &state, + const unitVec3dMag &fArea, + const bool &positive) const; + virtual squareMatrix InviscidConvJacobian( + const primVars &state, const unitVec3dMag &fArea) const; + virtual squareMatrix InviscidDissJacobian( + const primVars &state, const unitVec3dMag &fArea) const; + virtual double InviscidCellSpecRad(const primVars &state, + const unitVec3dMag &fAreaL, + const unitVec3dMag &fAreaR) const; + virtual double InviscidFaceSpecRad(const primVars &state, + const unitVec3dMag &fArea, + const bool &positive) const; + virtual squareMatrix ViscousJacobian(const primVars &state, + const unitVec3dMag &fArea, + const double &mu, const sutherland &suth, + const double &dist, const double &mut, + const double &f1) const; + virtual double ViscCellSpecRad(const primVars &state, const unitVec3dMag &fAreaL, - const unitVec3dMag &fAreaR) const; - virtual double ViscSpecRad(const primVars &state, - const unitVec3dMag &fAreaL, - const unitVec3dMag &fAreaR, - const idealGas &eos, const sutherland &suth, - const double &vol) const {return 0.0;} + const unitVec3dMag &fAreaR, + const double &mu, const sutherland &suth, + const double &vol, const double &mut, + const double &f1) const {return 0.0;} + virtual double ViscFaceSpecRad(const primVars &state, + const unitVec3dMag &fArea, + const double &mu, const sutherland &suth, + const double &dist, const double &mut, + const double &f1) const {return 0.0;} + tensor BoussinesqReynoldsStress(const primVars &state, const tensor &velGrad, const sutherland &suth, @@ -89,29 +113,41 @@ class turbModel { const vector3d &kGrad, const vector3d &wGrad) const; - double SpectralRadius(const primVars &state, - const unitVec3dMag &fAreaL, - const unitVec3dMag &fAreaR, - const idealGas &eos, const sutherland &suth, - const double &vol, const bool &addSrc) const; + double CellSpectralRadius(const primVars &state, + const unitVec3dMag &fAreaL, + const unitVec3dMag &fAreaR, + const double &mu, const sutherland &suth, + const double &vol, const double &mut, + const double & f1, const bool &addSrc) const; + double FaceSpectralRadius(const primVars &state, + const unitVec3dMag &fArea, + const double &mu, const sutherland &suth, + const double &dist, const double &mut, + const double & f1, const bool &positive) const; // abstract functions - virtual double CalcTurbSrc(const primVars &state, - const tensor &velGrad, - const vector3d &kGrad, - const vector3d &wGrad, - const sutherland &suth, const idealGas &eos, - const double &wallDist, const double &vol, - double &ksrc, double &wsrc) const = 0; - virtual double EddyViscAndMolecDiffCoeff(const primVars &state, - const tensor &vGrad, - const vector3d &kGrad, - const vector3d &wGrad, - const sutherland &suth, - const idealGas &eos, - const double &wallDist, - double &sigmaK, - double &sigmaW) const = 0; + virtual squareMatrix CalcTurbSrc(const primVars &state, + const tensor &velGrad, + const vector3d &kGrad, + const vector3d &wGrad, + const sutherland &suth, + const double &vol, + const double &mut, const double &f1, + double &ksrc, double &wsrc) const = 0; + virtual void EddyViscAndBlending(const primVars &state, + const tensor &vGrad, + const vector3d &kGrad, + const vector3d &wGrad, + const double &mu, + const double &wallDist, + const sutherland &suth, + double &mut, double &f1, + double &f2) const = 0; + virtual squareMatrix TurbSrcJac(const primVars &state, + const double &beta, + const sutherland &suth, + const double &vol) const = 0; + virtual void Print() const = 0; // destructor @@ -126,34 +162,51 @@ class turbNone : public turbModel { // move constructor and assignment operator turbNone(turbNone &&model) noexcept : turbModel(std::move(model)) {} - turbNone& operator=(turbNone&&) noexcept = default; + turbNone& operator=(turbNone&&) = default; // copy constructor and assignment operator turbNone(const turbNone &model) : turbModel(model) {} turbNone& operator=(const turbNone&) = default; // member functions - double CalcTurbSrc(const primVars &state, const tensor &velGrad, - const vector3d &kGrad, - const vector3d &wGrad, - const sutherland &suth, const idealGas &eos, - const double &wallDist, const double &vol, - double &ksrc, double &wsrc) const override; - double EddyViscAndMolecDiffCoeff(const primVars &state, - const tensor &velGrad, - const vector3d &kGrad, - const vector3d &wGrad, - const sutherland &suth, - const idealGas &eos, - const double &wallDist, double &sigmaK, - double &sigmaW) const override {return 0.0;} + squareMatrix CalcTurbSrc(const primVars &state, const tensor &velGrad, + const vector3d &kGrad, + const vector3d &wGrad, + const sutherland &suth, const double &vol, + const double &mut, const double &f1, double &ksrc, + double &wsrc) const override; + void EddyViscAndBlending(const primVars &state, + const tensor &vGrad, + const vector3d &kGrad, + const vector3d &wGrad, + const double &mu, + const double &wallDist, + const sutherland &suth, + double &mut, double &f1, + double &f2) const override {} double EddyViscNoLim(const primVars &state) const override {return 0.0;} - double InviscidSpecRad(const primVars &state, - const unitVec3dMag &fAreaL, - const unitVec3dMag &fAreaR) const override { + double InviscidCellSpecRad( + const primVars &state, const unitVec3dMag &fAreaL, + const unitVec3dMag &fAreaR) const override { + return 0.0; + } + double InviscidFaceSpecRad(const primVars &state, + const unitVec3dMag &fArea, + const bool &postive) const override { return 0.0; } + squareMatrix InviscidJacobian(const primVars &state, + const unitVec3dMag &fArea, + const bool &positive) const override; + squareMatrix InviscidConvJacobian( + const primVars &state, const unitVec3dMag &fArea) const override; + squareMatrix InviscidDissJacobian( + const primVars &state, const unitVec3dMag &fArea) const override; + squareMatrix TurbSrcJac(const primVars &state, const double &beta, + const sutherland &suth, + const double &vol) const override; + double TkeMin() const override {return 0.0;} double OmegaMin() const override {return 0.0;} @@ -189,32 +242,48 @@ class turbKWWilcox : public turbModel { // move constructor and assignment operator turbKWWilcox(turbKWWilcox &&model) noexcept : turbModel(std::move(model)) {} - turbKWWilcox& operator=(turbKWWilcox&&) noexcept = default; + turbKWWilcox& operator=(turbKWWilcox&&) = default; // copy constructor and assignment operator turbKWWilcox(const turbKWWilcox &model) : turbModel(model) {} turbKWWilcox& operator=(const turbKWWilcox&) = default; // member functions - double CalcTurbSrc(const primVars &, const tensor &, - const vector3d &, const vector3d &, - const sutherland &, const idealGas &, const double &, - const double &, double &, double &) const override; + squareMatrix CalcTurbSrc(const primVars &, const tensor &, + const vector3d &, const vector3d &, + const sutherland &, const double &, + const double &, const double &, double &, + double &) const override; double EddyVisc(const primVars&, const tensor &, const sutherland &, const double &) const override; - double EddyViscAndMolecDiffCoeff(const primVars &, const tensor &, - const vector3d &, - const vector3d &, const sutherland &, - const idealGas &, const double &, - double &, double &) const override; - + void EddyViscAndBlending(const primVars &, const tensor &, + const vector3d &, + const vector3d &, + const double &, const double &, + const sutherland &, double &, double &, + double &) const override; + bool UseUnlimitedEddyVisc() const override {return true;} double SrcSpecRad(const primVars &, const sutherland &, const double &) const override; - double ViscSpecRad(const primVars &, - const unitVec3dMag &, - const unitVec3dMag &, - const idealGas &, const sutherland &, - const double &) const override; + squareMatrix ViscousJacobian(const primVars &, + const unitVec3dMag &, + const double &, const sutherland &, + const double &, const double &, + const double &) const override; + double ViscCellSpecRad(const primVars &, + const unitVec3dMag &, + const unitVec3dMag &, + const double &, const sutherland &, + const double &, const double &, + const double &) const override; + double ViscFaceSpecRad(const primVars &, + const unitVec3dMag &, + const double &, const sutherland &, + const double &, const double &, + const double &) const override; + + squareMatrix TurbSrcJac(const primVars &, const double &, + const sutherland &, const double &) const override; double TurbPrandtlNumber() const override {return prt_;} double WallBeta() const override {return beta0_;} @@ -227,8 +296,8 @@ class turbKWWilcox : public turbModel { double Beta0() const {return beta0_;} double CLim() const {return clim_;} - double SigmaK() const override {return this->SigmaStar();} - double SigmaW() const override {return this->Sigma();} + double SigmaK(const double &f1) const override {return this->SigmaStar();} + double SigmaW(const double &f1) const override {return this->Sigma();} void Print() const override; @@ -257,7 +326,7 @@ class turbKWSst : public turbModel { double F2(const double &, const double &) const; double BlendedCoeff(const double &, const double &, const double &) const; double Alpha1(const primVars &, const sutherland &, const double &) const; - double Alpha2(const primVars &, const sutherland &, const idealGas &, + double Alpha2(const primVars &, const sutherland &, const double &, const double &) const; double Alpha3(const primVars &, const double &, const double &) const; @@ -269,32 +338,48 @@ class turbKWSst : public turbModel { // move constructor and assignment operator turbKWSst(turbKWSst &&model) noexcept : turbModel(std::move(model)) {} - turbKWSst& operator=(turbKWSst&&) noexcept = default; + turbKWSst& operator=(turbKWSst&&) = default; // copy constructor and assignment operator turbKWSst(const turbKWSst &model) : turbModel(model) {} turbKWSst& operator=(const turbKWSst&) = default; // member functions - double CalcTurbSrc(const primVars &, const tensor &, - const vector3d &, const vector3d &, - const sutherland &, const idealGas &, const double &, - const double &, double &, double &) const override; + squareMatrix CalcTurbSrc(const primVars &, const tensor &, + const vector3d &, const vector3d &, + const sutherland &, const double &, + const double &, const double &, double &, + double &) const override; double EddyVisc(const primVars &, const tensor &, const sutherland &, const double &) const override; - double EddyViscAndMolecDiffCoeff(const primVars &, const tensor &, - const vector3d &, - const vector3d &, const sutherland &, - const idealGas &, const double &, - double &, double &) const override; + void EddyViscAndBlending(const primVars &, const tensor &, + const vector3d &, + const vector3d &, + const double &, const double &, + const sutherland &, double &, double &, + double &) const override; double SrcSpecRad(const primVars &, const sutherland &, const double &) const override; - double ViscSpecRad(const primVars &, - const unitVec3dMag &, - const unitVec3dMag &, - const idealGas &, const sutherland &, - const double &) const override; + squareMatrix ViscousJacobian(const primVars &, + const unitVec3dMag &, + const double &, const sutherland &, + const double &, const double &, + const double &) const override; + double ViscCellSpecRad(const primVars &, + const unitVec3dMag &, + const unitVec3dMag &, + const double &, const sutherland &, + const double &, const double &, + const double &) const override; + double ViscFaceSpecRad(const primVars &, + const unitVec3dMag &, + const double &, const sutherland &, + const double &, const double &, + const double &) const override; + + squareMatrix TurbSrcJac(const primVars &, const double &, + const sutherland &, const double &) const override; double WallBeta() const override {return beta1_;} double TurbPrandtlNumber() const override {return prt_;} @@ -315,8 +400,12 @@ class turbKWSst : public turbModel { // use coefficients from 1 because they are smaller // this is used for TSL flux jacobian, so smaller will help increase // diagonal dominance of implicit operator - double SigmaK() const override {return this->SigmaK1();} - double SigmaW() const override {return this->SigmaW1();} + double SigmaK(const double &f1) const override { + return this->BlendedCoeff(sigmaK1_, sigmaK2_, f1); + } + double SigmaW(const double &f1) const override { + return this->BlendedCoeff(sigmaW1_, sigmaW2_, f1); + } void Print() const override; @@ -327,4 +416,6 @@ class turbKWSst : public turbModel { // function declarations + + #endif diff --git a/uncoupledScalar.hpp b/uncoupledScalar.hpp index b007fb5..ccc3911 100644 --- a/uncoupledScalar.hpp +++ b/uncoupledScalar.hpp @@ -19,6 +19,7 @@ #define UNCOUPLEDSCALARHEADERDEF // define the macro #include // cout +#include // max using std::cout; using std::endl; @@ -59,6 +60,9 @@ class uncoupledScalar { void SubtractFromFlowVariable(const double &s) {flowVar_ -= s;} void SubtractFromTurbVariable(const double &s) {turbVar_ -= s;} + double Max() const {return std::max(flowVar_, turbVar_);} + double Min() const {return std::min(flowVar_, turbVar_);} + void Zero() { flowVar_ = 0.0; turbVar_ = 0.0; diff --git a/utility.cpp b/utility.cpp new file mode 100644 index 0000000..60c6ef8 --- /dev/null +++ b/utility.cpp @@ -0,0 +1,727 @@ +/* This file is part of aither. + Copyright (C) 2015 Michael Nucci (michael.nucci@gmail.com) + + Aither 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. + + Aither 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 this program. If not, see . */ + +#include // cout, cerr, endl +#include // max, min +#include +#include +#include +#include "utility.hpp" +#include "procBlock.hpp" +#include "eos.hpp" // idealGas +#include "input.hpp" // inputVars +#include "genArray.hpp" +#include "turbulence.hpp" +#include "slices.hpp" +#include "fluxJacobian.hpp" +#include "kdtree.hpp" +#include "resid.hpp" + +using std::cout; +using std::endl; +using std::cerr; +using std::vector; +using std::string; +using std::max; +using std::min; +using std::unique_ptr; + +/* Function to calculate the gradient of a vector at the cell center using the +Green-Gauss method + +dU/dxj = (Sum) U * Aij / V (j=1,2,3) + i=1,nfaces + +The above equation shows how the gradient of a vector is calculated using the +Green-Gauss method. U is a vector. Aij is the area at face i (component j). +V is the volume of the control volume. X is the cartesian direction with +j indicating the component. The convention is for the area vectors to point out +of the control volume. + */ +tensor VectorGradGG( + const vector3d &vil, const vector3d &viu, + const vector3d &vjl, const vector3d &vju, + const vector3d &vkl, const vector3d &vku, + const vector3d &ail, const vector3d &aiu, + const vector3d &ajl, const vector3d &aju, + const vector3d &akl, const vector3d &aku, + const double &vol) { + // vil -- vector at the i-lower face of the cell at which the gradient + // is being calculated + // viu -- vector at the i-upper face of the cell at which the gradient + // is being calculated + // vjl -- vector at the j-lower face of the cell at which the gradient + // is being calculated + // vju -- vector at the j-upper face of the cell at which the gradient + // is being calculated + // vkl -- vector at the k-lower face of the cell at which the gradient + // is being calculated + // vku -- vector at the k-upper face of the cell at which the gradient + // is being calculated + + // ail -- area vector at the lower i-face of the cell at which the gradient + // is being calculated + // aiu -- area vector at the upper i-face of the cell at which the gradient + // is being calculated + // ajl -- area vector at the lower j-face of the cell at which the gradient + // is being calculated + // aju -- area vector at the upper j-face of the cell at which the gradient + // is being calculated + // akl -- area vector at the lower k-face of the cell at which the gradient + // is being calculated + // aku -- area vector at the upper k-face of the cell at which the gradient + // is being calculated + + // vol -- cell volume + + tensor temp; + const auto invVol = 1.0 / vol; + + // convention is for area vector to point out of cell, so lower values are + // negative, upper are positive + temp.SetXX(viu.X() * aiu.X() - vil.X() * ail.X() + vju.X() * aju.X() - + vjl.X() * ajl.X() + vku.X() * aku.X() - vkl.X() * akl.X()); + temp.SetXY(viu.Y() * aiu.X() - vil.Y() * ail.X() + vju.Y() * aju.X() - + vjl.Y() * ajl.X() + vku.Y() * aku.X() - vkl.Y() * akl.X()); + temp.SetXZ(viu.Z() * aiu.X() - vil.Z() * ail.X() + vju.Z() * aju.X() - + vjl.Z() * ajl.X() + vku.Z() * aku.X() - vkl.Z() * akl.X()); + + temp.SetYX(viu.X() * aiu.Y() - vil.X() * ail.Y() + vju.X() * aju.Y() - + vjl.X() * ajl.Y() + vku.X() * aku.Y() - vkl.X() * akl.Y()); + temp.SetYY(viu.Y() * aiu.Y() - vil.Y() * ail.Y() + vju.Y() * aju.Y() - + vjl.Y() * ajl.Y() + vku.Y() * aku.Y() - vkl.Y() * akl.Y()); + temp.SetYZ(viu.Z() * aiu.Y() - vil.Z() * ail.Y() + vju.Z() * aju.Y() - + vjl.Z() * ajl.Y() + vku.Z() * aku.Y() - vkl.Z() * akl.Y()); + + temp.SetZX(viu.X() * aiu.Z() - vil.X() * ail.Z() + vju.X() * aju.Z() - + vjl.X() * ajl.Z() + vku.X() * aku.Z() - vkl.X() * akl.Z()); + temp.SetZY(viu.Y() * aiu.Z() - vil.Y() * ail.Z() + vju.Y() * aju.Z() - + vjl.Y() * ajl.Z() + vku.Y() * aku.Z() - vkl.Y() * akl.Z()); + temp.SetZZ(viu.Z() * aiu.Z() - vil.Z() * ail.Z() + vju.Z() * aju.Z() - + vjl.Z() * ajl.Z() + vku.Z() * aku.Z() - vkl.Z() * akl.Z()); + + temp *= invVol; + + return temp; +} + +/* Function to calculate the gradient of a scalar at the cell center using the +Green-Gauss method + +dU/dxj = (Sum) U * Aij / V (j=1,2,3) + i=1,nfaces + +The above equation shows how the gradient of a scalar is calculated using the +Green-Gauss method. U is a scalar. Aij is the area at face i (component j). +V is the volume of the control volume. X is the cartesian direction with +j indicating the component. The convention is for the area vectors to point out +of the control volume. + */ +vector3d ScalarGradGG( + const double &til, const double &tiu, const double &tjl, const double &tju, + const double &tkl, const double &tku, const vector3d &ail, + const vector3d &aiu, const vector3d &ajl, + const vector3d &aju, const vector3d &akl, + const vector3d &aku, const double &vol) { + // til -- scalar value at the lower face of the cell at which the scalar + // gradient is being calculated + // tiu -- scalar value at the upper face of the cell at which the scalar + // gradient is being calculated + // tjl -- scalar value at the lower face of the cell at which the scalar + // gradient is being calculated + // tju -- scalar value at the upper face of the cell at which the scalar + // gradient is being calculated + // tkl -- scalar value at the lower face of the cell at which the scalar + // gradient is being calculated + // tku -- scalar value at the upper face of the cell at which the scalar + // gradient is being calculated + + // ail -- area vector at the lower face of the cell at which the scalar + // gradient is being calculated + // aiu -- area vector at the upper face of the cell at which the scalar + // gradient is being calculated + // ajl -- area vector at the lower face of the cell at which the scalar + // gradient is being calculated + // aju -- area vector at the upper face of the cell at which the scalar + // gradient is being calculated + // akl -- area vector at the lower face of the cell at which the scalar + // gradient is being calculated + // aku -- area vector at the upper face of the cell at which the scalar + // gradient is being calculated + + // vol -- cell volume + + vector3d temp; + const auto invVol = 1.0 / vol; + + // define scalar gradient vector + // convention is for area vector to point out of cell, so lower values are + // negative, upper are positive + temp.SetX(tiu * aiu.X() - til * ail.X() + tju * aju.X() - + tjl * ajl.X() + tku * aku.X() - tkl * akl.X()); + temp.SetY(tiu * aiu.Y() - til * ail.Y() + tju * aju.Y() - + tjl * ajl.Y() + tku * aku.Y() - tkl * akl.Y()); + temp.SetZ(tiu * aiu.Z() - til * ail.Z() + tju * aju.Z() - + tjl * ajl.Z() + tku * aku.Z() - tkl * akl.Z()); + + temp *= invVol; + + return temp; +} + +/* Function to swap ghost cell geometry between two blocks at an interblock +boundary. Slices are removed from the physical cells (extending into ghost cells +at the edges) of one block and inserted into the ghost cells of its partner +block. The reverse is also true. The slices are taken in the coordinate system +orientation of their parent block. + + Interior Cells Ghost Cells Ghost Cells Interior Cells + ________ ______|________ _________ _______________|_______ _________ +Ui-3/2 Ui-1/2 | Uj+1/2 Uj+3/2 Ui-3/2 Ui-1/2 | Uj+1/2 Uj+3/2 + | | | | | | | | | | + | Ui-1 | Ui | Uj | Uj+1 | | Ui-1 | Ui | Uj | Uj+1 | + | | | | | | | | | | + |________|______|________|_________| |________|______|_______|_________| + | | + +The above diagram shows the resulting values after the ghost cell swap. The +logic ensures that the ghost cells at the interblock boundary exactly match +their partner block as if there were no separation in the grid. + +Only 3 faces at each ghost cell need to be swapped (i.e. the lower face for Ui +is the upper face for Ui-1). At the end of a line (i-line, j-line or k-line), +both the upper and lower faces need to be swapped. +*/ +void SwapGeomSlice(interblock &inter, procBlock &blk1, procBlock &blk2) { + // inter -- interblock boundary information + // blk1 -- first block involved in interblock boundary + // blk2 -- second block involved in interblock boundary + + // Get indices for slice coming from first block to swap + auto is1 = 0; + auto ie1 = 0; + auto js1 = 0; + auto je1 = 0; + auto ks1 = 0; + auto ke1 = 0; + + inter.FirstSliceIndices(is1, ie1, js1, je1, ks1, ke1, blk1.NumGhosts()); + + // Get indices for slice coming from second block to swap + auto is2 = 0; + auto ie2 = 0; + auto js2 = 0; + auto je2 = 0; + auto ks2 = 0; + auto ke2 = 0; + + inter.SecondSliceIndices(is2, ie2, js2, je2, ks2, ke2, blk2.NumGhosts()); + + const auto geom1 = geomSlice(blk1, is1, ie1, js1, je1, ks1, ke1); + const auto geom2 = geomSlice(blk2, is2, ie2, js2, je2, ks2, ke2); + + // change interblocks to work with slice and ghosts + interblock inter1 = inter; + interblock inter2 = inter; + inter1.AdjustForSlice(false, blk1.NumGhosts()); + inter2.AdjustForSlice(true, blk2.NumGhosts()); + + // put slices in proper blocks + // return vector determining if any of the 4 edges of the interblock need to + // be updated for a "t" intersection + const auto adjEdge1 = blk1.PutGeomSlice(geom2, inter2, blk2.NumGhosts(), + blk2.NumGhosts()); + const auto adjEdge2 = blk2.PutGeomSlice(geom1, inter1, blk1.NumGhosts(), + blk1.NumGhosts()); + + // if an interblock border needs to be updated, update + for (auto ii = 0U; ii < adjEdge1.size(); ii++) { + if (adjEdge1[ii]) { + inter.UpdateBorderFirst(ii); + } + if (adjEdge2[ii]) { + inter.UpdateBorderSecond(ii); + } + } +} + + +/* Function to populate ghost cells with proper cell states for inviscid flow +calculation. This function operates on the entire grid and uses interblock +boundaries to pass the correct data between grid blocks. +*/ +void GetBoundaryConditions(vector &states, const input &inp, + const idealGas &eos, const sutherland &suth, + const unique_ptr &turb, + vector &connections, const int &rank, + const MPI_Datatype &MPI_cellData) { + // states -- vector of all procBlocks in the solution domain + // inp -- all input variables + // eos -- equation of state + // suth -- sutherland's law for viscosity + // connections -- vector of interblock connections + // rank -- processor rank + // MPI_cellData -- data type to pass primVars, genArray + + // loop over all blocks and assign inviscid ghost cells + for (auto ii = 0U; ii < states.size(); ii++) { + states[ii].AssignInviscidGhostCells(inp, eos, suth, turb); + } + + // loop over connections and swap ghost cells where needed + for (auto ii = 0U; ii < connections.size(); ii++) { + if (connections[ii].RankFirst() == rank && + connections[ii].RankSecond() == rank) { // both sides of interblock + // are on this processor, swap + // w/o mpi + states[connections[ii].LocalBlockFirst()] + .SwapStateSlice(connections[ii], + states[connections[ii].LocalBlockSecond()]); + } else if (connections[ii].RankFirst() == + rank) { // rank matches rank of first side of interblock, + // swap over mpi + states[connections[ii].LocalBlockFirst()] + .SwapStateSliceMPI(connections[ii], rank, MPI_cellData); + + } else if (connections[ii].RankSecond() == + rank) { // rank matches rank of second side of interblock, + // swap over mpi + states[connections[ii].LocalBlockSecond()] + .SwapStateSliceMPI(connections[ii], rank, MPI_cellData); + } + // if rank doesn't match either side of interblock, then do nothing and + // move on to the next interblock + } + + // loop over all blocks and get ghost cell edge data + for (auto ii = 0U; ii < states.size(); ii++) { + states[ii].AssignInviscidGhostCellsEdge(inp, eos, suth, turb); + } +} + + +// function to get face centers of cells on viscous walls +vector> GetViscousFaceCenters(const vector &blks) { + // blks -- vector of all procBlocks in simulation + + // get vector of BCs + vector bcs; + bcs.reserve(blks.size()); + for (auto ii = 0U; ii < blks.size(); ii++) { + bcs.push_back(blks[ii].BC()); + } + + // determine number of faces with viscous wall BC + auto nFaces = 0; + for (auto ii = 0U; ii < bcs.size(); ii++) { + nFaces += bcs[ii].NumViscousFaces(); + } + + // allocate vector for face centers + vector> faceCenters; + faceCenters.reserve(nFaces); + + const auto numG = blks[0].NumGhosts(); // number of ghost cells + + // store viscous face centers + for (auto aa = 0U; aa < bcs.size(); aa++) { // loop over BCs + for (auto bb = 0; bb < bcs[aa].NumSurfaces(); bb++) { // loop over surfaces + if (bcs[aa].GetBCTypes(bb) == "viscousWall") { + // only store face center if surface is viscous wall + + if (bcs[aa].GetSurfaceType(bb) <= 2) { // i-surface + const auto ii = (bcs[aa].GetSurfaceType(bb) % 2 == 0) + ? blks[aa].NumI() + numG : numG; + + for (auto jj = bcs[aa].GetJMin(bb) - 1 + numG; + jj < bcs[aa].GetJMax(bb) - 1 + numG; jj++) { + for (auto kk = bcs[aa].GetKMin(bb) - 1 + numG; + kk < bcs[aa].GetKMax(bb) - 1 + numG; kk++) { + faceCenters.push_back(blks[aa].FCenterI(ii, jj, kk)); + } + } + } else if (bcs[aa].GetSurfaceType(bb) <= 4) { // j-surface + const auto jj = (bcs[aa].GetSurfaceType(bb) % 2 == 0) + ? blks[aa].NumJ() + numG : numG; + + for (auto ii = bcs[aa].GetIMin(bb) - 1 + numG; + ii < bcs[aa].GetIMax(bb) - 1 + numG; ii++) { + for (auto kk = bcs[aa].GetKMin(bb) - 1 + numG; + kk < bcs[aa].GetKMax(bb) - 1 + numG; kk++) { + faceCenters.push_back(blks[aa].FCenterJ(ii, jj, kk)); + } + } + } else { // k-surface + const auto kk = (bcs[aa].GetSurfaceType(bb) % 2 == 0) + ? blks[aa].NumK() + numG : numG; + + for (auto ii = bcs[aa].GetIMin(bb) - 1 + numG; + ii < bcs[aa].GetIMax(bb) - 1 + numG; ii++) { + for (auto jj = bcs[aa].GetJMin(bb) - 1 + numG; + jj < bcs[aa].GetJMax(bb) - 1 + numG; jj++) { + faceCenters.push_back(blks[aa].FCenterK(ii, jj, kk)); + } + } + } + } + } + } + return faceCenters; +} + + +// function to calculate the distance to the nearest viscous wall of all +// cell centers +void CalcWallDistance(vector &localBlocks, const kdtree &tree) { + for (auto &block : localBlocks) { + block.CalcWallDistance(tree); + } +} + +// function to take in a vector of procBlocks and return a vector of the +// conservative variable states +vector> GetCopyConsVars(const vector &blocks, + const idealGas &eos) { + vector> consVars(blocks.size()); + + for (auto ii = 0U; ii < blocks.size(); ii++) { + consVars[ii] = blocks[ii].GetCopyConsVars(eos); + } + return consVars; +} + +void ExplicitUpdate(vector &blocks, + const input &inp, const idealGas &eos, + const double &aRef, const sutherland &suth, + const vector> &solTimeN, + const unique_ptr &turb, const int &mm, + genArray &residL2, resid &residLinf) { + // create dummy update (not used in explicit update) + multiArray3d du(1, 1, 1); + // loop over all blocks and update + for (auto bb = 0U; bb < blocks.size(); bb++) { + blocks[bb].UpdateBlock(inp, eos, aRef, suth, du, solTimeN[bb], + turb, mm, residL2, residLinf); + } +} + + +double ImplicitUpdate(vector &blocks, + vector> &mainDiagonal, + const input &inp, const idealGas &eos, + const double &aRef, const sutherland &suth, + const vector> &solTimeN, + const vector> &solDeltaMmN, + vector> &solDeltaNm1, + const unique_ptr &turb, const int &mm, + genArray &residL2, resid &residLinf, + const vector &connections, const int &rank, + const MPI_Datatype &MPI_cellData) { + // blocks -- vector of procBlocks on current processor + // mainDiagonal -- main diagonal of A matrix for all blocks on processor + // inp -- input variables + // eos -- equation of state + // suth -- sutherland's law for viscosity + // solTimeN -- solution at time N + // solDeltaMmN -- solution at time M minus solution at time N + // solDeltaNm1 -- solution at time N minus 1 + // turb -- turbulence model + // mm -- nonlinear iteration + // residL2 -- L2 residual + // residLinf -- L infinity residual + + // initialize matrix error + auto matrixError = 0.0; + + const auto numG = blocks[0].NumGhosts(); + + // add volume and time term and calculate inverse of main diagonal + for (auto bb = 0U; bb < blocks.size(); bb++) { + blocks[bb].InvertDiagonal(mainDiagonal[bb], inp); + } + + // initialize matrix update + vector> du(blocks.size()); + for (auto bb = 0U; bb < blocks.size(); bb++) { + du[bb] = blocks[bb].InitializeMatrixUpdate(inp, solDeltaMmN[bb], + solDeltaNm1[bb], + mainDiagonal[bb]); + } + + // Solve Ax=b with supported solver + if (inp.MatrixSolver() == "lusgs" || inp.MatrixSolver() == "blusgs") { + // calculate order by hyperplanes for each block + vector>> reorder(blocks.size()); + for (auto bb = 0U; bb < blocks.size(); bb++) { + reorder[bb] = HyperplaneReorder(blocks[bb].NumI(), blocks[bb].NumJ(), + blocks[bb].NumK()); + } + + // start sweeps through domain + for (auto ii = 0; ii < inp.MatrixSweeps(); ii++) { + // swap updates for ghost cells + SwapImplicitUpdate(du, connections, rank, MPI_cellData, numG); + + // forward lu-sgs sweep + for (auto bb = 0U; bb < blocks.size(); bb++) { + blocks[bb].LUSGS_Forward(reorder[bb], du[bb], solDeltaMmN[bb], + solDeltaNm1[bb], eos, inp, suth, turb, + mainDiagonal[bb], ii); + } + + // swap updates for ghost cells + SwapImplicitUpdate(du, connections, rank, MPI_cellData, numG); + + // backward lu-sgs sweep + for (auto bb = 0U; bb < blocks.size(); bb++) { + matrixError += blocks[bb].LUSGS_Backward(reorder[bb], du[bb], + solDeltaMmN[bb], + solDeltaNm1[bb], eos, inp, + suth, turb, mainDiagonal[bb], + ii); + } + } + } else if (inp.MatrixSolver() == "dplur" || inp.MatrixSolver() == "bdplur") { + for (auto ii = 0; ii < inp.MatrixSweeps(); ii++) { + // swap updates for ghost cells + SwapImplicitUpdate(du, connections, rank, MPI_cellData, numG); + + for (auto bb = 0U; bb < blocks.size(); bb++) { + // Calculate correction (du) + matrixError += blocks[bb].DPLUR(du[bb], solDeltaMmN[bb], + solDeltaNm1[bb], eos, inp, suth, turb, + mainDiagonal[bb]); + } + } + } else { + cerr << "ERROR: Matrix solver " << inp.MatrixSolver() << + " is not recognized!" << endl; + cerr << "Please choose lusgs, blusgs, dplur, or bdplur." << endl; + exit(EXIT_FAILURE); + } + + // Update blocks and reset main diagonal + for (auto bb = 0U; bb < blocks.size(); bb++) { + // Update solution + blocks[bb].UpdateBlock(inp, eos, aRef, suth, du[bb], solTimeN[bb], + turb, mm, residL2, residLinf); + + // Assign time n to time n-1 at end of nonlinear iterations + if (inp.TimeIntegration() == "bdf2" && + mm == inp.NonlinearIterations() - 1 ) { + solDeltaNm1[bb] = blocks[bb].DeltaNMinusOne(solTimeN[bb], eos, + inp.Theta(), inp.Zeta()); + } + + // zero flux jacobians + mainDiagonal[bb].Zero(); + } + + return matrixError; +} + +void SwapImplicitUpdate(vector> &du, + const vector &connections, const int &rank, + const MPI_Datatype &MPI_cellData, + const int &numGhosts) { + // du -- implicit update in conservative variables + // connections -- interblock boundary conditions + // rank -- processor rank + // MPI_cellData -- datatype to pass primVars or genArray + // numGhosts -- number of ghost cells + + // loop over all connections and swap interblock updates when necessary + for (auto ii = 0U; ii < connections.size(); ii++) { + if (connections[ii].RankFirst() == rank && + connections[ii].RankSecond() == rank) { + // both sides of interblock are on this processor, swap w/o mpi + du[connections[ii].LocalBlockFirst()].SwapSlice(connections[ii], + du[connections[ii].LocalBlockSecond()], numGhosts, numGhosts); + } else if (connections[ii].RankFirst() == rank) { + // rank matches rank of first side of interblock, swap over mpi + du[connections[ii].LocalBlockFirst()] + .SwapSliceMPI(connections[ii], rank, MPI_cellData, numGhosts); + + } else if (connections[ii].RankSecond() == rank) { + // rank matches rank of second side of interblock, swap over mpi + du[connections[ii].LocalBlockSecond()] + .SwapSliceMPI(connections[ii], rank, MPI_cellData, numGhosts); + } + // if rank doesn't match either side of interblock, then do nothing and + // move on to the next interblock + } +} + + +void SwapTurbVars(vector &states, + const vector &connections, const int &rank, + const int &numGhosts) { + // states -- vector of all procBlocks in the solution domain + // connections -- interblock boundary conditions + // rank -- processor rank + // numGhosts -- number of ghost cells + + // loop over all connections and swap interblock updates when necessary + for (auto ii = 0U; ii < connections.size(); ii++) { + if (connections[ii].RankFirst() == rank && + connections[ii].RankSecond() == rank) { + // both sides of interblock are on this processor, swap w/o mpi + states[connections[ii].LocalBlockFirst()].SwapTurbSlice( + connections[ii], states[connections[ii].LocalBlockSecond()]); + } else if (connections[ii].RankFirst() == rank) { + // rank matches rank of first side of interblock, swap over mpi + states[connections[ii].LocalBlockFirst()].SwapTurbSliceMPI( + connections[ii], rank); + + } else if (connections[ii].RankSecond() == rank) { + // rank matches rank of second side of interblock, swap over mpi + states[connections[ii].LocalBlockSecond()].SwapTurbSliceMPI( + connections[ii], rank); + } + // if rank doesn't match either side of interblock, then do nothing and + // move on to the next interblock + } +} + + +void CalcResidual(vector &states, + vector> &mainDiagonal, + const sutherland &suth, const idealGas &eos, + const input &inp, const unique_ptr &turb, + const vector &connections, const int &rank, + const int &numGhosts) { + // states -- vector of all procBlocks on processor + // mainDiagonal -- main diagonal of A matrix for implicit solve + // suth -- sutherland's law for viscosity + // eos -- equation of state + // inp -- input variables + // turb -- turbulence model + // connections -- interblock boundary conditions + // rank -- processor rank + // numGhosts -- number of layers of ghost cells + + for (auto bb = 0U; bb < states.size(); bb++) { + // calculate residual + states[bb].CalcResidualNoSource(suth, eos, inp, turb, mainDiagonal[bb]); + } + + if (inp.IsTurbulent()) { + // swap turbulence varibles calculated during residual calculation + SwapTurbVars(states, connections, rank, numGhosts); + + for (auto bb = 0U; bb < states.size(); bb++) { + // calculate source terms for residual + states[bb].CalcSrcTerms(suth, turb, inp, mainDiagonal[bb]); + } + } +} + +void CalcTimeStep(vector &states, const input &inp, + const double &aRef) { + // states -- vector of all procBlocks on processor + // inp -- input variables + // aRef -- reference speed of sound + + for (auto bb = 0U; bb < states.size(); bb++) { + // calculate time step + states[bb].CalcBlockTimeStep(inp, aRef); + } +} + + +// function to reorder the block by hyperplanes +/*A hyperplane is a plane of i+j+k=constant within an individual block. The +LUSGS solver must sweep along these hyperplanes to avoid +calculating a flux jacobian. Ex. The solver must visit all points on hyperplane +1 before visiting any points on hyperplane 2. +*/ +vector> HyperplaneReorder(const int &imax, const int &jmax, + const int &kmax) { + // total number of hyperplanes in a given block + const auto numPlanes = imax + jmax + kmax - 2; + vector> reorder; + reorder.reserve(imax * jmax * kmax); + + for (auto pp = 0; pp < numPlanes; pp++) { + for (auto kk = 0; kk < kmax; kk++) { + for (auto jj = 0; jj < jmax; jj++) { + for (auto ii = 0; ii < imax; ii++) { + if (ii + jj + kk == pp) { // if sum of ii, jj, and kk equals pp than + // point is on hyperplane pp + reorder.push_back(vector3d(ii, jj, kk)); + } + } + } + } + } + + return reorder; +} + +void GetSolMMinusN(vector> &solMMinusN, + const vector &states, + const vector> &solN, + const idealGas &eos, const input &inp, const int &mm) { + // solMMinusN -- solution at time m minus solution at time n + // solN -- solution at time n + // eos -- equation of state + // inp -- input variables + // mm -- nonlinear iteration + + for (auto bb = 0U; bb < solMMinusN.size(); bb++) { + solMMinusN[bb] = states[bb].SolTimeMMinusN(solN[bb], eos, inp, mm); + } +} + + +void ResizeArrays(const vector &states, const input &inp, + vector> &sol, + vector> &jac) { + // states -- all states on processor + // sol -- vector of solutions to be resized + // jac -- vector of flux jacobians to be resized + + for (auto bb = 0U; bb < states.size(); bb++) { + sol[bb].ClearResize(states[bb].NumI(), states[bb].NumJ(), + states[bb].NumK()); + + const auto fluxJac = inp.IsBlockMatrix() ? + fluxJacobian(inp.NumFlowEquations(), inp.NumTurbEquations()) : + fluxJacobian(1, 1); + + jac[bb].ClearResize(states[bb].NumI(), states[bb].NumJ(), + states[bb].NumK(), fluxJac); + } +} + + +vector3d TauNormal(const tensor &velGrad, + const vector3d &area, const double &mu, + const double &mut, const sutherland &suth) { + // get 2nd coefficient of viscosity assuming bulk viscosity is 0 (Stoke's) + const auto lambda = suth.Lambda(mu + mut); + + // wall shear stress + return lambda * velGrad.Trace() * area + (mu + mut) * + (velGrad.MatMult(area) + velGrad.Transpose().MatMult(area)); +} + + + + + + + diff --git a/utility.hpp b/utility.hpp new file mode 100644 index 0000000..fca3828 --- /dev/null +++ b/utility.hpp @@ -0,0 +1,148 @@ +/* This file is part of aither. + Copyright (C) 2015 Michael Nucci (michael.nucci@gmail.com) + + Aither 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. + + Aither 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 this program. If not, see . */ + +#ifndef UTILITYHEADERDEF // only if the macro UTILITYHEADERDEF is not + // defined execute these lines of code +#define UTILITYHEADERDEF // define the macro + +#include // vector +#include +#include "mpi.h" // parallelism +#include "vector3d.hpp" // vector3d +#include "multiArray3d.hpp" // multiArray3d +#include "tensor.hpp" // tensor +#include "macros.hpp" + +using std::vector; +using std::unique_ptr; + +// forward class declarations +class procBlock; +class idealGas; +class sutherland; +class input; +class genArray; +class turbModel; +class fluxJacobian; +class kdtree; +class resid; + + +// function definitions +template +inline T FaceReconCentral(const T &, const T &, const vector3d &, + const vector3d &, const vector3d &); + +tensor VectorGradGG(const vector3d &, const vector3d &, + const vector3d &, const vector3d &, + const vector3d &, const vector3d &, + const vector3d &, const vector3d &, + const vector3d &, const vector3d &, + const vector3d &, const vector3d &, + const double &); + +vector3d ScalarGradGG( + const double &, const double &, const double &, const double &, + const double &, const double &, const vector3d &, + const vector3d &, const vector3d &, + const vector3d &, const vector3d &, + const vector3d &, const double &); + +void SwapGeomSlice(interblock &, procBlock &, procBlock &); + +void GetBoundaryConditions(vector &, const input &, const idealGas &, + const sutherland &, const unique_ptr &, + vector &, const int &, + const MPI_Datatype &); + +vector> GetViscousFaceCenters(const vector &); +void CalcWallDistance(vector &, const kdtree &); + +vector> GetCopyConsVars(const vector &, + const idealGas &); + +void ExplicitUpdate(vector &, const input &, const idealGas &, + const double &, const sutherland &, + const vector> &, + const unique_ptr &, const int &, genArray &, + resid &); +double ImplicitUpdate(vector &, vector> &, + const input &, const idealGas &, const double &, + const sutherland &, + const vector> &, + const vector> &, + vector> &, + const unique_ptr &, + const int &, genArray &, resid &, + const vector &, const int &, + const MPI_Datatype &); + +void SwapImplicitUpdate(vector> &, + const vector &, const int &, + const MPI_Datatype &, const int &); +void SwapTurbVars(vector &, const vector &, const int &, + const int &); + +void CalcResidual(vector &, + vector> &, + const sutherland &, const idealGas &, const input &, + const unique_ptr &, + const vector &, const int &, const int &); + +void CalcTimeStep(vector &, const input &, const double &); + +void GetSolMMinusN(vector> &, const vector &, + const vector> &, + const idealGas &, const input &, const int &); + +// function to reorder block by hyperplanes +vector> HyperplaneReorder(const int &, const int &, const int &); + +void ResizeArrays(const vector &, const input &, + vector> &, + vector> &); + +vector3d TauNormal(const tensor &, const vector3d &, + const double &, const double &, const sutherland &); +// --------------------------------------------------------------------------- +// inline function definitions + +// function to reconstruct cell variables to the face using central +// differences +template +T FaceReconCentral(const T &varU, const T &varD, const vector3d &pU, + const vector3d &pD, const vector3d &pF) { + // varU -- variable at the cell center of the upwind cell + // varD -- variable at the cell center of the downwind cell + // pU -- position of the cell center of the upwind cell + // pD -- position of the cell center of the downwind cell + // pF -- position of the face center of the face on which the reconstruction + // is happening + + // distance from cell center to cell center + const auto cen2cen = pU.Distance(pD); + // distance from upwind cell center to cell face + const auto up2face = pU.Distance(pF); + // ratio of distance from upwind cell center to cell face to center to center + const auto upRatio = up2face / cen2cen; + + // reconstruct with central difference + return varD * upRatio + varU * (1.0 - upRatio); +} + + +#endif + diff --git a/vector3d.hpp b/vector3d.hpp index 3241191..583d583 100644 --- a/vector3d.hpp +++ b/vector3d.hpp @@ -107,6 +107,7 @@ class vector3d { T Distance(const vector3d&) const; T DistSq(const vector3d&) const; vector3d Normalize() const; + void Zero(); // destructor ~vector3d() noexcept {} @@ -155,7 +156,7 @@ class unitVec3dMag { return *this; } - // access of data_ members + // access of data members vector3d UnitVector() const { return unitVec_; } T X() const { return unitVec_.X(); } T Y() const { return unitVec_.Y(); } @@ -365,6 +366,15 @@ vector3d vector3d::Normalize() const { return (*this) / this->Mag(); } +// Function to zero out a vector +template +void vector3d::Zero() { + for (auto &val : data_) { + val = 0; + } +} + + // ----------------------------------------------------------------- // Functions for unitVec3dMag class // Function to calculate the dot product of two vectors @@ -456,7 +466,7 @@ inline const unitVec3dMag operator/(const T &lhs, unitVec3dMag rhs) { template ostream &operator<<(ostream &os, const unitVec3dMag &v) { - os << v.Vector() << ", " << v.Mag(); + os << v.UnitVector() << ", " << v.Mag(); return os; } diff --git a/viscousFlux.cpp b/viscousFlux.cpp index 5a65d5b..2ebf446 100644 --- a/viscousFlux.cpp +++ b/viscousFlux.cpp @@ -22,6 +22,7 @@ #include "primVars.hpp" // primVars #include "turbulence.hpp" // turbModel #include "matrix.hpp" // squareMatrix +#include "utility.hpp" // TauNormal using std::cout; using std::endl; @@ -59,7 +60,8 @@ viscousFlux::viscousFlux( const idealGas &eqnState, const vector3d &tGrad, const vector3d &normArea, const vector3d &tkeGrad, const vector3d &omegaGrad, const unique_ptr &turb, - const primVars &state, const double &wallDist) { + const primVars &state, const double &lamVisc, const double &turbVisc, + const double &f1) { // velGrad -- velocity gradient tensor // suth -- method to get viscosity (Sutherland's law) // eqnState -- equation of state @@ -69,26 +71,20 @@ viscousFlux::viscousFlux( // omegaGrad -- omega gradient // turb -- turbulence model // state -- primative variables at face - // wallDist -- distance to nearest viscous wall + // lamVisc -- laminar viscosity + // turbVisc -- turbulent viscosity + // f1 -- first blending coefficient - // get laminar viscosity - const auto mu = suth.EffectiveViscosity(state.Temperature(eqnState)); + // get viscosity with nondimensional normalization + const auto mu = suth.NondimScaling() * lamVisc; + const auto mut = suth.NondimScaling() * turbVisc; - // get turbulent eddy viscosity and molecular diffusion coefficient for - // turbulence equations - auto tkeCoeff = 0.0; - auto omgCoeff = 0.0; - const auto mut = turb->EddyViscAndMolecDiffCoeff(state, velGrad, tkeGrad, - omegaGrad, suth, eqnState, - wallDist, tkeCoeff, - omgCoeff); - - // get 2nd coefficient of viscosity assuming bulk viscosity is 0 (Stoke's) - const auto lambda = suth.Lambda(mu + mut); + // get molecular diffusion coefficients for turbulence equations + const auto tkeCoeff = turb->SigmaK(f1); + const auto omgCoeff = turb->SigmaW(f1); // wall shear stress - const auto tau = lambda * velGrad.Trace() * normArea + (mu + mut) * - (velGrad.MatMult(normArea) + velGrad.Transpose().MatMult(normArea)); + const auto tau = TauNormal(velGrad, normArea, mu, mut, suth); data_[0] = tau.X(); data_[1] = tau.Y(); @@ -99,8 +95,12 @@ viscousFlux::viscousFlux( tGrad.DotProd(normArea); // turbulence viscous flux - data_[4] = (mu + tkeCoeff * mut) * tkeGrad.DotProd(normArea); - data_[5] = (mu + omgCoeff * mut) * omegaGrad.DotProd(normArea); + // some turbulence models use the unlimited eddy viscosity for the + // turbulence viscous flux instead of the limited eddy viscosity + const auto mutt = turb->UseUnlimitedEddyVisc() ? + suth.NondimScaling() * turb->EddyViscNoLim(state) : mut; + data_[4] = (mu + tkeCoeff * mutt) * tkeGrad.DotProd(normArea); + data_[5] = (mu + omgCoeff * mutt) * omegaGrad.DotProd(normArea); } // non-member functions @@ -117,236 +117,9 @@ ostream &operator<<(ostream &os, viscousFlux &flux) { return os; } -// function to calculate the thin shear layer flux jacobian -- NOT USED in LUSGS -// formulation -// void CalcTSLFluxJac(const double &mu, const double &eddyVisc, -// const idealGas &eqnState, const vector3d &normArea, -// const primVars &left, const primVars &right, -// const double &dist, squareMatrix &dFv_dUl, -// squareMatrix &dFv_dUr, const sutherland &suth, -// const double &prt) { -// // mu -- dynamic viscosity -// // eddyVisc -- turbulent eddy viscosity -// // eqnState -- equation of state -// // normArea -- unit area vector of face -// // left -- left state (primative) -// // right -- right state (primative) -// // dist -- distance from centroid of left cell to centroid of right cell -// // dFv_dUl -- flux jacobian of viscous flux with respect to left state -// // dFV_dUr -- flux jacobian of viscous flux with respect to right state -// // suth -- method to get viscosity as a function of temperature - -// // check to make sure square matrices are of correct size -// if (dFv_dUl.Size() != 5 || dFv_dUr.Size() != 5) { -// cerr << "ERROR: Error in viscousFlux.cpp:CalcTSLFluxJac. Problem with thin " -// "shear layer viscous jacobian calculation. The input jacobian " -// "matrices are not of the correct size!" << endl; -// exit(0); -// } - -// // get velocity at face -// const auto vel = 0.5 * (right.Velocity() + left.Velocity()); - -// // calculate thin shear layer velocity gradients -// const auto velGradTSL = CalcVelGradTSL(left, right, normArea, dist); - -// // calculate bulk viscosity -// const auto lambda = suth.Lambda(mu + eddyVisc); - -// // calculate shear stress at face -// const auto velGradTrace = velGradTSL.Trace(); -// const auto tau = lambda * velGradTrace * normArea + -// (mu + eddyVisc) * (velGradTSL.MatMult(normArea) + -// velGradTSL.Transpose().MatMult(normArea)); - -// // calculate coefficients (from Blazek) -// const auto theta = normArea.MagSq(); -// const auto thetaX = (4.0 / 3.0) * normArea.X() * normArea.X() + -// normArea.Y() * normArea.Y() + normArea.Z() * normArea.Z(); -// const auto thetaY = normArea.X() * normArea.X() + -// (4.0 / 3.0) * normArea.Y() * normArea.Y() + -// normArea.Z() * normArea.Z(); -// const auto thetaZ = normArea.X() * normArea.X() + normArea.Y() * -// normArea.Y() + (4.0 / 3.0) * normArea.Z() * normArea.Z(); - -// const auto etaX = (1.0 / 3.0) * normArea.Y() * normArea.Z(); -// const auto etaY = (1.0 / 3.0) * normArea.X() * normArea.Z(); -// const auto etaZ = (1.0 / 3.0) * normArea.X() * normArea.Y(); - -// const auto piX = vel.X() * thetaX + vel.Y() * etaZ + vel.Z() * etaY; -// const auto piY = vel.X() * etaZ + vel.Y() * thetaY + vel.Z() * etaX; -// const auto piZ = vel.X() * etaY + vel.Y() * etaX + vel.Z() * thetaZ; - -// const auto phiRhoL = -1.0 * (eqnState.Conductivity(mu) + -// eqnState.TurbConductivity(eddyVisc, prt)) * -// left.Temperature(eqnState) / ((mu + eddyVisc) * left.Rho()); -// const auto phiRhoR = -1.0 * (eqnState.Conductivity(mu) + -// eqnState.TurbConductivity(eddyVisc, prt)) * -// right.Temperature(eqnState) / -// ((mu + eddyVisc) * right.Rho()); - -// const auto phiPressL = (eqnState.Conductivity(mu) + -// eqnState.TurbConductivity(eddyVisc, prt)) / -// ((mu + eddyVisc) * left.Rho()); -// const auto phiPressR = (eqnState.Conductivity(mu) + -// eqnState.TurbConductivity(eddyVisc, prt)) / -// ((mu + eddyVisc) * right.Rho()); - -// // calculate matrix - derivative of left primative vars wrt left conservative -// // vars -// squareMatrix dWl_dUl(5); -// dWl_dUl.Zero(); - -// // column 0 -// dWl_dUl.SetData(0, 0, 1.0); -// dWl_dUl.SetData(1, 0, -1.0 * left.U() / left.Rho()); -// dWl_dUl.SetData(2, 0, -1.0 * left.V() / left.Rho()); -// dWl_dUl.SetData(3, 0, -1.0 * left.W() / left.Rho()); -// dWl_dUl.SetData(4, 0, -// 0.5 * (eqnState.Gamma() - 1.0) * left.Velocity().MagSq()); - -// // column 1 -// dWl_dUl.SetData(1, 1, 1.0 / left.Rho()); -// dWl_dUl.SetData(4, 1, -1.0 * (eqnState.Gamma() - 1.0) * left.U()); - -// // column 2 -// dWl_dUl.SetData(2, 2, 1.0 / left.Rho()); -// dWl_dUl.SetData(4, 2, -1.0 * (eqnState.Gamma() - 1.0) * left.V()); - -// // column 3 -// dWl_dUl.SetData(3, 3, 1.0 / left.Rho()); -// dWl_dUl.SetData(4, 3, -1.0 * (eqnState.Gamma() - 1.0) * left.W()); - -// // column 4 -// dWl_dUl.SetData(4, 4, eqnState.Gamma() - 1.0); - -// //------------------------------------------------------------------------- -// // calculate matrix - derivative of right primative vars wrt right -// // conservative vars -// squareMatrix dWr_dUr(5); -// dWr_dUr.Zero(); - -// // column 0 -// dWr_dUr.SetData(0, 0, 1.0); -// dWr_dUr.SetData(1, 0, -1.0 * right.U() / right.Rho()); -// dWr_dUr.SetData(2, 0, -1.0 * right.V() / right.Rho()); -// dWr_dUr.SetData(3, 0, -1.0 * right.W() / right.Rho()); -// dWr_dUr.SetData(4, 0, -// 0.5 * (eqnState.Gamma() - 1.0) * right.Velocity().MagSq()); - -// // column 1 -// dWr_dUr.SetData(1, 1, 1.0 / right.Rho()); -// dWr_dUr.SetData(4, 1, -1.0 * (eqnState.Gamma() - 1.0) * right.U()); - -// // column 2 -// dWr_dUr.SetData(2, 2, 1.0 / right.Rho()); -// dWr_dUr.SetData(4, 2, -1.0 * (eqnState.Gamma() - 1.0) * right.V()); - -// // column 3 -// dWr_dUr.SetData(3, 3, 1.0 / right.Rho()); -// dWr_dUr.SetData(4, 3, -1.0 * (eqnState.Gamma() - 1.0) * right.W()); - -// // column 4 -// dWr_dUr.SetData(4, 4, eqnState.Gamma() - 1.0); - -// //------------------------------------------------------------------------ -// // calculate matrix - derivative of viscous flux wrt left primative vars -// // column 0 -// dFv_dUl.SetData(0, 0, 0.0); -// dFv_dUl.SetData(1, 0, 0.0); -// dFv_dUl.SetData(2, 0, 0.0); -// dFv_dUl.SetData(3, 0, 0.0); -// dFv_dUl.SetData(4, 0, phiRhoL * theta); - -// // column 1 -// dFv_dUl.SetData(0, 1, 0.0); -// dFv_dUl.SetData(1, 1, thetaX); -// dFv_dUl.SetData(2, 1, etaZ); -// dFv_dUl.SetData(3, 1, etaY); -// dFv_dUl.SetData(4, 1, -0.5 * (dist / (mu + eddyVisc)) * tau.X() + piX); - -// // column 2 -// dFv_dUl.SetData(0, 2, 0.0); -// dFv_dUl.SetData(1, 2, etaZ); -// dFv_dUl.SetData(2, 2, thetaY); -// dFv_dUl.SetData(3, 2, etaX); -// dFv_dUl.SetData(4, 2, -0.5 * (dist / (mu + eddyVisc)) * tau.Y() + piY); - -// // column 3 -// dFv_dUl.SetData(0, 3, 0.0); -// dFv_dUl.SetData(1, 3, etaY); -// dFv_dUl.SetData(2, 3, etaX); -// dFv_dUl.SetData(3, 3, thetaZ); -// dFv_dUl.SetData(4, 3, -0.5 * (dist / (mu + eddyVisc)) * tau.Z() + piZ); - -// // column 4 -// dFv_dUl.SetData(0, 4, 0.0); -// dFv_dUl.SetData(1, 4, 0.0); -// dFv_dUl.SetData(2, 4, 0.0); -// dFv_dUl.SetData(3, 4, 0.0); -// dFv_dUl.SetData(4, 4, phiPressL * theta); - -// dFv_dUl = -1.0 * ((mu + eddyVisc) / dist) * dFv_dUl; - -// //----------------------------------------------------------------------- -// // calculate matrix - derivative of viscous flux wrt right primative vars -// // column 0 -// dFv_dUr.SetData(0, 0, 0.0); -// dFv_dUr.SetData(1, 0, 0.0); -// dFv_dUr.SetData(2, 0, 0.0); -// dFv_dUr.SetData(3, 0, 0.0); -// dFv_dUr.SetData(4, 0, phiRhoR * theta); - -// // column 1 -// dFv_dUr.SetData(0, 1, 0.0); -// dFv_dUr.SetData(1, 1, thetaX); -// dFv_dUr.SetData(2, 1, etaZ); -// dFv_dUr.SetData(3, 1, etaY); -// dFv_dUr.SetData(4, 1, 0.5 * (dist / (mu + eddyVisc)) * tau.X() + piX); - -// // column 2 -// dFv_dUr.SetData(0, 2, 0.0); -// dFv_dUr.SetData(1, 2, etaZ); -// dFv_dUr.SetData(2, 2, thetaY); -// dFv_dUr.SetData(3, 2, etaX); -// dFv_dUr.SetData(4, 2, 0.5 * (dist / (mu + eddyVisc)) * tau.Y() + piY); - -// // column 3 -// dFv_dUr.SetData(0, 3, 0.0); -// dFv_dUr.SetData(1, 3, etaY); -// dFv_dUr.SetData(2, 3, etaX); -// dFv_dUr.SetData(3, 3, thetaZ); -// dFv_dUr.SetData(4, 3, 0.5 * (dist / (mu + eddyVisc)) * tau.Z() + piZ); - -// // column 4 -// dFv_dUr.SetData(0, 4, 0.0); -// dFv_dUr.SetData(1, 4, 0.0); -// dFv_dUr.SetData(2, 4, 0.0); -// dFv_dUr.SetData(3, 4, 0.0); -// dFv_dUr.SetData(4, 4, phiPressR * theta); - -// dFv_dUr = ((mu + eddyVisc) / dist) * dFv_dUr; - -// // multiply by dW_dU to get flux jacobian derivative wrt conservative -// // variables -// dFv_dUl = dFv_dUl * dWl_dUl; -// dFv_dUr = dFv_dUr * dWr_dUr; - -// // calculate spectral radius -// const auto faceState = 0.5 * (left + right); -// dFv_dUl.Identity(); -// dFv_dUr.Identity(); -// const auto specRad = (mu + eddyVisc) * eqnState.Gamma() / -// (eqnState.Prandtl() * faceState.Rho() * dist); - -// // add or subtract spectral radius to flux jacobian -// dFv_dUl = -1.0 * specRad * dFv_dUl; -// dFv_dUr = specRad * dFv_dUr; -// } // function to calculate the velocity gradients at a cell face using the Thin // Shear Layer approximation -// NOT USED in LUSGS formulation tensor CalcVelGradTSL(const primVars &left, const primVars &right, const vector3d &normArea, const double &dist) { diff --git a/viscousFlux.hpp b/viscousFlux.hpp index 52b27c4..717a3a5 100644 --- a/viscousFlux.hpp +++ b/viscousFlux.hpp @@ -53,7 +53,8 @@ class viscousFlux { viscousFlux(const tensor&, const sutherland&, const idealGas&, const vector3d&, const vector3d&, const vector3d&, const vector3d&, - const unique_ptr&, const primVars&, const double&); + const unique_ptr&, const primVars&, + const double&, const double&, const double&); // move constructor and assignment operator viscousFlux(viscousFlux&&) noexcept = default;