void CSourcePieceWise_TurbSA::ComputeResidual(double *val_residual, double **val_Jacobian_i, double **val_Jacobian_j, CConfig *config) { if (incompressible) { Density_i = DensityInc_i; } else { Density_i = U_i[0]; } val_residual[0] = 0.0; Production = 0; Destruction = 0; CrossProduction = 0; val_Jacobian_i[0][0] = 0.0; /*--- Computation of vorticity ---*/ Vorticity = (PrimVar_Grad_i[2][0]-PrimVar_Grad_i[1][1])*(PrimVar_Grad_i[2][0]-PrimVar_Grad_i[1][1]); if (nDim == 3) Vorticity += ( (PrimVar_Grad_i[3][1]-PrimVar_Grad_i[2][2])*(PrimVar_Grad_i[3][1]-PrimVar_Grad_i[2][2]) + (PrimVar_Grad_i[1][2]-PrimVar_Grad_i[3][0])*(PrimVar_Grad_i[1][2]-PrimVar_Grad_i[3][0]) ); Omega = sqrt(Vorticity); /*--- Rotational correction term ---*/ if (rotating_frame) { div = PrimVar_Grad_i[1][0] + PrimVar_Grad_i[2][1]; if (nDim == 3) div += PrimVar_Grad_i[3][2]; StrainMag = 0.0; // add diagonals StrainMag += pow(PrimVar_Grad_i[1][0] - 1.0/3.0*div,2.0); StrainMag += pow(PrimVar_Grad_i[2][1] - 1.0/3.0*div,2.0); if (nDim == 3) StrainMag += pow(PrimVar_Grad_i[3][2] - 1.0/3.0*div,2.0); // add off diagonals StrainMag += 2.0*pow(0.5*(PrimVar_Grad_i[1][1]+PrimVar_Grad_i[2][0]),2.0); if (nDim == 3) { StrainMag += 2.0*pow(0.5*(PrimVar_Grad_i[1][2]+PrimVar_Grad_i[3][0]),2.0); StrainMag += 2.0*pow(0.5*(PrimVar_Grad_i[2][2]+PrimVar_Grad_i[3][1]),2.0); } StrainMag = sqrt(2.0*StrainMag); Omega += 2.0*min(0.0,StrainMag-Omega); } if (dist_i > 1e-10) { /*--- Production term ---*/ dist_i_2 = dist_i*dist_i; nu = Laminar_Viscosity_i/Density_i; Ji = TurbVar_i[0]/nu; Ji_2 = Ji*Ji; Ji_3 = Ji_2*Ji; fv1 = Ji_3/(Ji_3+cv1_3); fv2 = 1.0 - Ji/(1.0+Ji*fv1); S = Omega; inv_k2_d2 = 1.0/(k2*dist_i_2); Shat = S + TurbVar_i[0]*fv2*inv_k2_d2; inv_Shat = 1.0/max(Shat, 1.0e-10); /*--- Production term ---*/; if (!transition) Production = cb1*Shat*TurbVar_i[0]*Volume; else Production = cb1*Shat*TurbVar_i[0]*Volume*intermittency; /*--- Destruction term ---*/ r = min(TurbVar_i[0]*inv_Shat*inv_k2_d2,10.0); g = r + cw2*(pow(r,6.0)-r); g_6 = pow(g,6.0); glim = pow((1.0+cw3_6)/(g_6+cw3_6),1.0/6.0); fw = g*glim; if (!transition) Destruction = cw1*fw*TurbVar_i[0]*TurbVar_i[0]/dist_i_2*Volume; else Destruction = cw1*fw*TurbVar_i[0]*TurbVar_i[0]/dist_i_2*Volume*min(max(intermittency,0.1),1.0); /*--- Diffusion term ---*/ norm2_Grad = 0.0; for (iDim = 0; iDim < nDim; iDim++) norm2_Grad += TurbVar_Grad_i[0][iDim]*TurbVar_Grad_i[0][iDim]; CrossProduction = cb2_sigma*norm2_Grad*Volume; val_residual[0] = Production - Destruction + CrossProduction; /*--- Implicit part ---*/ /*--- Production term ---*/ dfv1 = 3.0*Ji_2*cv1_3/(nu*pow(Ji_3+cv1_3,2.)); dfv2 = -(1/nu-Ji_2*dfv1)/pow(1.+Ji*fv1,2.); if ( Shat <= 1.0e-10 ) dShat = 0.0; else dShat = (fv2+TurbVar_i[0]*dfv2)*inv_k2_d2; val_Jacobian_i[0][0] += cb1*(TurbVar_i[0]*dShat+Shat)*Volume; /*--- Destruction term ---*/ dr = (Shat-TurbVar_i[0]*dShat)*inv_Shat*inv_Shat*inv_k2_d2; if (r == 10.0) dr = 0.0; dg = dr*(1.+cw2*(6.*pow(r,5.)-1.)); dfw = dg*glim*(1.-g_6/(g_6+cw3_6)); val_Jacobian_i[0][0] -= cw1*(dfw*TurbVar_i[0] + 2.*fw)*TurbVar_i[0]/dist_i_2*Volume; } for (int i =0; i < nDim; i++){ for (int j=0; j < nDim; j++){ DUiDXj[i][j] = PrimVar_Grad_i[i+1][j]; } DNuhatDXj[i] = TurbVar_Grad_i[0][i]; } SAInputs->Set(DUiDXj, DNuhatDXj, rotating_frame, transition, dist_i, Laminar_Viscosity_i, Density_i, TurbVar_i[0], intermittency); SpalartAllmarasSourceTerm(SAInputs, SAConstants, testResidual, testJacobian); for (int i=0; i < nResidual; i++){ testResidual[i] *= Volume; } for (int i=0; i < nJacobian; i++){ testJacobian[i] *= Volume; } // Check if the old and new match //for (int i = 0; i < nResidual; i++){ if (abs(Production - testResidual[0]) > 1e-15){ cout << "Production doesn't match" << endl; cout << "diff is " << Production - testResidual[0] << endl; exit(10); } if (abs(Destruction - testResidual[1]) > 1e-15){ cout << "Destruction doesn't match" << endl; exit(10); } if (abs(CrossProduction - testResidual[2]) > 1e-15){ cout << "cpp Cross " << CrossProduction << endl; cout << "Func cross " << testResidual[2] << endl; cout << "dist_i " << dist_i << endl; cout << "Cross production doesn't match" << endl; exit(10); } if (abs(val_residual[0]-testResidual[3]) > 1e-15){ cout << "Val residual is " << val_residual[0] << endl; cout << "Test residual is " << testResidual[3] << endl; cout << "Diff is " << val_residual[0] - testResidual[3] << endl; cout << "Full residual doesn't match" << endl; exit(10); } }
void CSourcePieceWise_TurbML::ComputeResidual(double *val_residual, double **val_Jacobian_i, double **val_Jacobian_j, CConfig *config) { if (incompressible) { Density_i = DensityInc_i; } else { Density_i = U_i[0]; } /* Intialize */ // Note that the Production, destruction, etc. are all volume independent val_residual[0] = 0.0; SAProduction = 0; SADestruction = 0; SACrossProduction = 0; SASource = 0; MLProduction = 0; MLDestruction = 0; MLCrossProduction = 0; MLSource = 0; SourceDiff = 0; val_Jacobian_i[0][0] = 0.0; for (int i =0; i < nDim; i++){ for (int j=0; j < nDim; j++){ DUiDXj[i][j] = PrimVar_Grad_i[i+1][j]; } DNuhatDXj[i] = TurbVar_Grad_i[0][i]; } /* Call Spalart-Allmaras (for comparison) */ SAInputs->Set(DUiDXj, DNuhatDXj, rotating_frame, transition, dist_i, Laminar_Viscosity_i, Density_i, TurbVar_i[0], intermittency); SpalartAllmarasSourceTerm(SAInputs, SAConstants, testResidual, testJacobian); SAProduction = testResidual[0]; SADestruction = testResidual[1]; SACrossProduction = testResidual[2]; SASource = testResidual[3]; for (int i=0; i < nResidual; i++){ testResidual[i] *= Volume; } for (int i=0; i < nJacobian; i++){ testJacobian[i] *= Volume; } /* Call turbulence model */ // Get all the variables int nInputMLVariables = 9; int nOutputMLVariables = 1; double * input = new double[nInputMLVariables]; for (int i = 0; i < nInputMLVariables; i++){ input[i] = 0; } int ctr = 0; input[ctr] = Laminar_Viscosity_i/Density_i; ctr++; input[ctr] = TurbVar_i[0]; ctr++; input[ctr] = dist_i; ctr++; for (iDim = 0; iDim < nDim; iDim++){ input[ctr] = TurbVar_Grad_i[0][iDim]; ctr++; } for (iDim = 0; iDim < nDim; iDim ++){ for (int jDim = 0; jDim < nDim; jDim++){ input[ctr] = PrimVar_Grad_i[iDim+1][iDim]; ctr++; } } if (ctr != nInputMLVariables){ cout << "Improper number of variables put into ctr"<< endl; exit(1); } double *output = new double[nOutputMLVariables]; for (int i=0; i < nOutputMLVariables; i++){ output[i] = 0; } this->MLModel->Predict(input, output); // Should add some sort of switch in the future MLSource = output[0]; SourceDiff = MLSource - SASource; // Rescale by volume output[0] = output[0]*Volume; /* double slideIter = 500.0; double extiter = double(config->GetExtIter()); if (extiter > slideIter){ extiter = slideIter; } val_residual[0] = testResidual[3]*(slideIter - extiter)/slideIter + output[0] * extiter/slideIter; */ // cout.precision(15); /* cout <<"ml pred is " << output[0] << endl; cout << "real SA is " << testResidual[3] << endl; cout << "val resid is " << val_residual[0] << endl; */ val_residual[0] = output[0]; val_residual[0] = testResidual[3]; //val_Jacobian_i[0][0] = testJacobian[0]; delete input; delete output; }
void CSourcePieceWise_TurbML::ComputeResidual(double *val_residual, double **val_Jacobian_i, double **val_Jacobian_j, CConfig *config) { if (incompressible) { Density_i = V_i[nDim+1]; Laminar_Viscosity_i = V_i[nDim+3]; } else { Density_i = V_i[nDim+2]; Laminar_Viscosity_i = V_i[nDim+5]; } /* Intialize */ // Note that the Production, destruction, etc. are all volume independent for (int i= 0; i < nResidual; i++){ SAResidual[i] = 0; SANondimResidual[i] = 0; Residual[i] = 0; NondimResidual[i] = 0; ResidualDiff[i] = 0; NondimResidualDiff[i] = 0; } val_residual[0] = 0.0; val_Jacobian_i[0][0] = 0.0; NuhatGradNorm = 0; for (int i =0; i < nDim; i++){ for (int j=0; j < nDim; j++){ DUiDXj[i][j] = PrimVar_Grad_i[i+1][j]; } DNuhatDXj[i] = TurbVar_Grad_i[0][i]; NuhatGradNorm += TurbVar_Grad_i[0][i] * TurbVar_Grad_i[0][i]; } /* Call Spalart-Allmaras (for comparison) */ SAInputs->Set(DUiDXj, DNuhatDXj, rotating_frame, transition, dist_i, Laminar_Viscosity_i, Density_i, TurbVar_i[0], intermittency); SpalartAllmarasSourceTerm(SAInputs, SAConstants,SAResidual, SAJacobian, SAOtherOutputs); this->SANondimInputs -> Set(SAInputs); for (int i=0; i < nResidual; i++){ SANondimResidual[i] = SAResidual[i]; } SANondimInputs->NondimensionalizeSource(nResidual, SANondimResidual); int nInputMLVariables = 0; int nOutputMLVariables = 0; double* netInput = NULL; double* netOutput = NULL; if (featureset.compare("SA") == 0){ // Set the output equal to the spalart allmaras output. for (int i = 0; i < nResidual; i++){ Residual[i] = SAResidual[i]; NondimResidual[i] = SANondimResidual[i]; } }else if (featureset.compare("nondim_production")==0){ nInputMLVariables = 2; nOutputMLVariables = 1; netInput = new double[nInputMLVariables]; netOutput = new double[nOutputMLVariables]; netInput[0] = SANondimInputs->Chi; netInput[1] = SANondimInputs->OmegaBar; // Predict using Nnet MLModel->Predict(netInput, netOutput); // Gather all the appropriate variables NondimResidual[0] = netOutput[0]; NondimResidual[1] = SANondimResidual[1]; NondimResidual[2] = SANondimResidual[2]; NondimResidual[3] = NondimResidual[0] - NondimResidual[1] + NondimResidual[2]; for (int i=0; i < nResidual; i++){ Residual[i] = NondimResidual[i]; //cout << "NondimResidual " << i <<" "<< NondimResidual[i] << endl; } SANondimInputs->DimensionalizeSource(nResidual, Residual); /* for (int i=0; i < nResidual; i++){ cout << "DimResidual " << i << " " << Residual[i] << endl; } */ }else if(featureset.compare("nondim_production_log") == 0){ nInputMLVariables = 2; nOutputMLVariables = 1; netInput = new double[nInputMLVariables]; netOutput = new double[nOutputMLVariables]; netInput[0] = log10(SANondimInputs->Chi); netInput[1] = log10(SANondimInputs->OmegaBar); // Predict using Nnet MLModel->Predict(netInput, netOutput); // Gather all the appropriate variables NondimResidual[0] = netOutput[0]; NondimResidual[1] = SANondimResidual[1]; NondimResidual[2] = SANondimResidual[2]; NondimResidual[3] = NondimResidual[0] - NondimResidual[1] + NondimResidual[2]; for (int i=0; i < nResidual; i++){ Residual[i] = NondimResidual[i]; // cout << "NondimResidual " << i << NondimResidual[i] << endl; } SANondimInputs->DimensionalizeSource(nResidual, Residual); /* for (int i=0; i < nResidual; i++){ cout << "DimResidual " << i << Residual[i] << endl; } */ }else if(featureset.compare("nondim_production_logchi") == 0){ nInputMLVariables = 2; nOutputMLVariables = 1; netInput = new double[nInputMLVariables]; netOutput = new double[nOutputMLVariables]; netInput[0] = log10(SANondimInputs->Chi); netInput[1] = SANondimInputs->OmegaBar; // Predict using Nnet MLModel->Predict(netInput, netOutput); // Gather all the appropriate variables NondimResidual[0] = netOutput[0]; NondimResidual[1] = SANondimResidual[1]; NondimResidual[2] = SANondimResidual[2]; NondimResidual[3] = NondimResidual[0] - NondimResidual[1] + NondimResidual[2]; for (int i=0; i < nResidual; i++){ Residual[i] = NondimResidual[i]; } SANondimInputs->DimensionalizeSource(nResidual, Residual); }else if(featureset.compare("production")==0){ nInputMLVariables = 3; nOutputMLVariables = 1; netInput = new double[nInputMLVariables]; netOutput = new double[nOutputMLVariables]; netInput[0] = SANondimInputs->Chi; netInput[1] = SANondimInputs->OmegaBar; netInput[2] = SANondimInputs->SourceNondim; // cout << "Net inputs "; // for (int i = 0; i < 3; i++){ // cout << "\t" << netInput[i]; // } // cout << endl; // Predict using Nnet MLModel->Predict(netInput, netOutput); // Gather the appropriate values Residual[0] = netOutput[0]; Residual[1] = SAResidual[1]; Residual[2] = SAResidual[2]; Residual[3] = Residual[0] - Residual[1] + Residual[2]; // cout << "ML Production " << Residual[0] << endl; // cout << "SA Production " << SAResidual[0] << endl; for (int i=0; i < nResidual; i++){ NondimResidual[i] = Residual[i]; } SANondimInputs->NondimensionalizeSource(nResidual, NondimResidual); }else if (featureset.compare("nondim_destruction")==0){ nInputMLVariables = 2; nOutputMLVariables = 1; netInput = new double[nInputMLVariables]; netOutput = new double[nOutputMLVariables]; netInput[0] = SANondimInputs->Chi; netInput[1] = SANondimInputs->OmegaBar; MLModel->Predict(netInput, netOutput); NondimResidual[0] = SANondimResidual[0]; NondimResidual[1] = netOutput[0]; NondimResidual[2] = SANondimResidual[2]; NondimResidual[3] = NondimResidual[0] - NondimResidual[1] + NondimResidual[2]; for (int i=0; i < nResidual; i++){ Residual[i] = NondimResidual[i]; } SANondimInputs->DimensionalizeSource(nResidual, Residual); }else if(featureset.compare("destruction")==0){ nInputMLVariables = 3; nOutputMLVariables = 1; netInput = new double[nInputMLVariables]; netOutput = new double[nOutputMLVariables]; netInput[0] = SANondimInputs->Chi; netInput[1] = SANondimInputs->OmegaBar; netInput[2] = SANondimInputs->SourceNondim; // Predict using Nnet MLModel->Predict(netInput, netOutput); // Gather the appropriate values Residual[0] = SAResidual[0]; Residual[1] = netOutput[1]; Residual[2] = SAResidual[2]; Residual[3] = Residual[0] - Residual[1] + Residual[2]; for (int i=0; i < nResidual; i++){ NondimResidual[i] = Residual[i]; } SANondimInputs->NondimensionalizeSource(nResidual, NondimResidual); }else if (featureset.compare("nondim_crossproduction")==0){ nInputMLVariables = 2; nOutputMLVariables = 1; netInput = new double[nInputMLVariables]; netOutput = new double[nOutputMLVariables]; netInput[0] = SANondimInputs->Chi; netInput[1] = SANondimInputs->NuHatGradNormBar; //cout << "IN nondim_crossproduction " << endl; // cout << "chi " << netInput[0] << endl; // cout << "grad norm bar "<< netInput[1] << endl; MLModel->Predict(netInput, netOutput); NondimResidual[0] = SANondimResidual[0]; NondimResidual[1] = SANondimResidual[1]; NondimResidual[2] = netOutput[0]; NondimResidual[3] = NondimResidual[0] - NondimResidual[1] + NondimResidual[2]; for (int i=0; i < nResidual; i++){ Residual[i] = NondimResidual[i]; } SANondimInputs->DimensionalizeSource(nResidual, Residual); }else if (featureset.compare("nondim_source")==0){ nInputMLVariables = 3; nOutputMLVariables = 1; netInput = new double[nInputMLVariables]; netOutput = new double[nOutputMLVariables]; netInput[0] = SANondimInputs->Chi; netInput[1] = SANondimInputs->OmegaBar; netInput[2] = SANondimInputs->NuHatGradNormBar; // Predict using Nnet MLModel->Predict(netInput, netOutput); NondimResidual[0] = 0; NondimResidual[1] = 0; NondimResidual[2] = 0; NondimResidual[3] = netOutput[0]; for (int i=0; i < nResidual; i++){ Residual[i] = NondimResidual[i]; } SANondimInputs->DimensionalizeSource(nResidual, Residual); }else if (featureset.compare("fw_les_2")==0){ nOutputMLVariables = 1; netInput = new double[nInputMLVariables]; netOutput = new double[nOutputMLVariables]; double chi = SANondimInputs->Chi; double omegaBar = SANondimInputs->OmegaBar; // Karthik nondimensionalizes by d / vhat whereas I do by /(v + vhat) omegaBar *= 1 + 1/chi; netInput[0] = chi; netInput[1] = omegaBar; MLModel->Predict(netInput, netOutput); double safw = SAOtherOutputs->fw; double newfw = netOutput[0]; if (newfw < -1){ newfw = 1; } if (newfw > 6){ newfw = 6; } // The output is the value of fw. Need to replace the destruction term with the new computation double turbKinVisc = SAInputs->Turbulent_Kinematic_Viscosity; double dist2 = SAInputs->dist * SAInputs->dist; double newdestruction = SAConstants->cw1 * (newfw +safw) * turbKinVisc * turbKinVisc / dist2; for (int i= 0; i < nResidual; i++){ Residual[i] = SAResidual[i]; } Residual[1] = newdestruction; Residual[3] = Residual[0] + Residual[1] + Residual[2]; for (int i= 0; i < nResidual; i++){ NondimResidual[i] = Residual[i]; } SANondimInputs->NondimensionalizeSource(nResidual, NondimResidual); }else{ cout << "None of the conditions met" << endl; cout << "featureset is " << featureset << endl; throw "ML_Turb_Model_Nondimensionalization not recognized"; } delete [] netInput; delete [] netOutput; // Hack if the wall distance is too low if (dist_i < 1e-10){ for (int i= 0; i < nResidual; i++){ Residual[i] = 0; NondimResidual[i] = 0; } } // Now that we have found the ML Residual and the SA residual, see if there are // any special hacks that we should use unsigned short nStrings = config->GetNumML_Turb_Model_Extra(); string *extraString = config->GetML_Turb_Model_Extra(); if (nStrings > 0){ if (extraString[0].compare("FlatplateBlOnlyCutoff") == 0){ // Only use ML in the boundary layer and have a sharp cutoff if ((Coord_i[0] < 0) || (Coord_i[1]) > 0.06 ){ // Not in the BL, so just use the SA residual for (int i = 0; i < nResidual; i++){ Residual[i] = SAResidual[i]; NondimResidual[i] = SANondimResidual[i]; } } } } // cout << "SA nondim cross production " << SANondimResidual[2] << endl; // cout << "Nondim cross production " << NondimResidual[2] << endl; // cout << "SA cross production " << SAResidual[2] << endl; // cout << "Cross production " << Residual[2] << endl; // Compute the differences for (int i = 0; i < nResidual; i++){ ResidualDiff[i] = Residual[i] - SAResidual[i]; NondimResidualDiff[i] = NondimResidual[i] - SANondimResidual[i]; } // Store The residual for the outer structure val_residual[0] = Residual[3] * Volume; val_Jacobian_i[0][0] = SAJacobian[0] * Volume; /* cout << "Sa resid "; for (int i = 0; i < nResidual; i++){ cout << SAResidual[i] << "\t"; } cout << endl; cout << "Ml resid "; for (int i = 0; i < nResidual; i++){ cout << Residual[i] << "\t"; } cout << endl; */ }