// A fill specialized to the single node at the coupling interface void ConvDiff_PDE::computeHeatFlux( const Epetra_Vector * soln ) { int numDep = depProblems.size(); // Create the overlapped solution and position vectors Epetra_Vector u(*OverlapMap); Epetra_Vector uold(*OverlapMap); std::vector<Epetra_Vector*> dep(numDep); for( int i = 0; i < numDep; ++i) dep[i] = new Epetra_Vector(*OverlapMap); Epetra_Vector xvec(*OverlapMap); // Export Solution to Overlap vector // If the vector to be used in the fill is already in the Overlap form, // we simply need to map on-processor from column-space indices to // OverlapMap indices. Note that the old solution is simply fixed data that // needs to be sent to an OverlapMap (ghosted) vector. The conditional // treatment for the current soution vector arises from use of // FD coloring in parallel. uold.Import(*oldSolution, *Importer, Insert); for( int i = 0; i < numDep; ++i ) (*dep[i]).Import(*( (*(depSolutions.find(depProblems[i]))).second ), *Importer, Insert); xvec.Import(*xptr, *Importer, Insert); if( NULL == soln ) u.Import(*initialSolution, *Importer, Insert); else u.Import(*soln, *Importer, Insert); // Declare required variables int row; double * xx = new double[2]; double * uu = new double[2]; double * uuold = new double[2]; std::vector<double*> ddep(numDep); for( int i = 0; i < numDep; ++i) ddep[i] = new double[2]; Basis basis; // Bundle up the dependent variables in the way needed for computing // the source terms of each reaction map<string, double*> depVars; depVars.insert( pair< std::string, double*>(getName(), uu) ); for( int i = 0; i < numDep; ++i ) depVars.insert( pair<string, double*>(myManager->getProblemName(depProblems[i]), ddep[i]) ); myFlux = 0.0; // Loop Over Gauss Points for( int gp = 0; gp < 2; ++gp ) { // Get the solution and coordinates at the nodes xx[0]=xvec[interface_elem]; xx[1]=xvec[interface_elem+1]; uu[0] = u[interface_elem]; uu[1] = u[interface_elem+1]; uuold[0] = uold[interface_elem]; uuold[1] = uold[interface_elem+1]; for( int i = 0; i < numDep; ++i ) { ddep[i][0] = (*dep[i])[interface_elem]; ddep[i][1] = (*dep[i])[interface_elem+1]; } // Calculate the basis function and variables at the gauss points basis.getBasis(gp, xx, uu, uuold, ddep); row = OverlapMap->GID( interface_elem + local_node ); if( StandardMap->MyGID(row) ) { myFlux += + basis.wt * basis.dx * ( peclet * (basis.duu / basis.dx) * basis.phi[local_node] + kappa * (1.0/(basis.dx*basis.dx)) * basis.duu * basis.dphide[local_node] ); } } // Sync up processors to be safe Comm->Barrier(); // Cleanup for( int i = 0; i < numDep; ++i) { delete [] ddep[i]; delete dep[i]; } delete [] xx ; delete [] uu ; delete [] uuold ; //int lastDof = StandardMap->LID(StandardMap->MaxAllGID()); //cout << "\t\"" << myName << "\" u[0] = " << u[0] // << "\tu[N] = " << u[lastDof] << std::endl; //cout << u << std::endl; //cout << "\t\"" << myName << "\" myFlux = " << myFlux << std::endl << std::endl; // Scale domain integration according to interface position myFlux *= dirScale; // Now add radiation contribution to flux myFlux += radiation * ( pow(u[interface_node], 4) - pow(u[opposite_node], 4) ); return; }
// Matrix and Residual Fills bool HMX_PDE::evaluate( NOX::Epetra::Interface::Required::FillType flag, const Epetra_Vector* soln, Epetra_Vector* tmp_rhs) { // Determine what to fill (F or Jacobian) bool fillF = false; bool fillMatrix = false; if (tmp_rhs != 0) { fillF = true; rhs = tmp_rhs; } else { fillMatrix = true; } // "flag" can be used to determine how accurate your fill of F should be // depending on why we are calling evaluate (Could be using computeF to // populate a Jacobian or Preconditioner). if (flag == NOX::Epetra::Interface::Required::Residual) { // Do nothing for now } else if (flag == NOX::Epetra::Interface::Required::Jac) { // Do nothing for now } else if (flag == NOX::Epetra::Interface::Required::Prec) { // Do nothing for now } else if (flag == NOX::Epetra::Interface::Required::User) { // Do nothing for now } int numDep = depProblems.size(); // Create the overlapped solution and position vectors Epetra_Vector u(*OverlapMap); Epetra_Vector uold(*OverlapMap); std::vector<Epetra_Vector*> dep(numDep); for( int i = 0; i<numDep; i++) dep[i] = new Epetra_Vector(*OverlapMap); Epetra_Vector xvec(*OverlapMap); // Export Solution to Overlap vector // If the vector to be used in the fill is already in the Overlap form, // we simply need to map on-processor from column-space indices to // OverlapMap indices. Note that the old solution is simply fixed data that // needs to be sent to an OverlapMap (ghosted) vector. The conditional // treatment for the current soution vector arises from use of // FD coloring in parallel. uold.Import(*oldSolution, *Importer, Insert); for( int i = 0; i<numDep; i++ ) (*dep[i]).Import(*( (*(depSolutions.find(depProblems[i]))).second ), *Importer, Insert); xvec.Import(*xptr, *Importer, Insert); if( flag == NOX::Epetra::Interface::Required::FD_Res) // Overlap vector for solution received from FD coloring, so simply reorder // on processor u.Export(*soln, *ColumnToOverlapImporter, Insert); else // Communication to Overlap vector is needed u.Import(*soln, *Importer, Insert); // Declare required variables int OverlapNumMyNodes = OverlapMap->NumMyElements(); int OverlapMinMyNodeGID; if (MyPID==0) OverlapMinMyNodeGID = StandardMap->MinMyGID(); else OverlapMinMyNodeGID = StandardMap->MinMyGID()-1; // Setup iterators for looping over each problem source term contribution // to this one's PDE map<string, double>::iterator srcTermIter; map<string, double>::iterator srcTermEnd = SrcTermWeight.end(); // Bundle up the dependent variables in the way needed for computing // the source terms of each reaction /* Epetra_Vector debugSrcTerm(*OverlapMap); map<string, Epetra_Vector*> debugDepVars; debugDepVars.insert( pair<string, Epetra_Vector*>(getName(), &u) ); for( int i = 0; i<numDep; i++ ) debugDepVars.insert( pair<string, Epetra_Vector*> (myManager->getName(depProblems[i]), &dep[i]) ); for( srcTermIter = SrcTermWeight.begin(); srcTermIter != srcTermEnd; srcTermIter++) { HMX_PDE &srcTermProb = dynamic_cast<HMX_PDE&>( myManager->getProblem(srcTermIter->first) ); std::cout << "Inside problem: \"" << getName() << "\" calling to get source term " << "from problem: \"" << srcTermIter->first << "\" :" << std::endl; srcTermProb.computeSourceTerm(debugDepVars, debugSrcTerm); std::cout << "Resulting source term :" << debugSrcTerm << std::endl; } */ int row; double alpha = 500.0; double xx[2]; double uu[2]; double uuold[2]; std::vector<double*> ddep(numDep); for( int i = 0; i<numDep; i++) ddep[i] = new double[2]; double *srcTerm = new double[2]; Basis basis; // Bundle up the dependent variables in the way needed for computing // the source terms of each reaction map<string, double*> depVars; depVars.insert( pair<string, double*>(getName(), uu) ); for( int i = 0; i<numDep; i++ ) depVars.insert( pair<string, double*> (myManager->getProblemName(depProblems[i]), ddep[i]) ); // Do a check on this fill // map<string, double*>::iterator iter; // for( iter = depVars.begin(); iter != depVars.end(); iter++) // std::cout << "Inserted ... " << iter->first << "\t" << iter->second << std::endl; // std::cout << "--------------------------------------------------" << std::endl; // for( iter = depVars.begin(); iter != depVars.end(); iter++) // std::cout << iter->first << "\t" << (iter->second)[0] << ", " // << (iter->second)[1] << std::endl; // std::cout << "--------------------------------------------------" << std::endl; // Zero out the objects that will be filled if ( fillMatrix ) A->PutScalar(0.0); if ( fillF ) rhs->PutScalar(0.0); // Loop Over # of Finite Elements on Processor for (int ne=0; ne < OverlapNumMyNodes-1; ne++) { // Loop Over Gauss Points for(int gp=0; gp < 2; gp++) { // Get the solution and coordinates at the nodes xx[0]=xvec[ne]; xx[1]=xvec[ne+1]; uu[0] = u[ne]; uu[1] = u[ne+1]; uuold[0] = uold[ne]; uuold[1] = uold[ne+1]; for( int i = 0; i<numDep; i++ ) { ddep[i][0] = (*dep[i])[ne]; ddep[i][1] = (*dep[i])[ne+1]; } // Calculate the basis function and variables at the gauss points basis.getBasis(gp, xx, uu, uuold, ddep); // Loop over Nodes in Element for (int i=0; i< 2; i++) { row=OverlapMap->GID(ne+i); if (StandardMap->MyGID(row)) { if ( fillF ) { // First do time derivative and diffusion operator (*rhs)[StandardMap->LID(OverlapMap->GID(ne+i))]+= +basis.wt*basis.dx *((basis.uu - basis.uuold)/dt * basis.phi[i] +(1.0/(basis.dx*basis.dx))*diffCoef*basis.duu*basis.dphide[i]); // Then do source term contributions // for( srcTermIter = SrcTermWeight.begin(); srcTermIter != srcTermEnd; srcTermIter++) { HMX_PDE &srcTermProb = dynamic_cast<HMX_PDE&>( myManager->getProblem((*srcTermIter).first) ); srcTermProb.computeSourceTerm(2, depVars, srcTerm); (*rhs)[StandardMap->LID(OverlapMap->GID(ne+i))]+= +basis.wt*basis.dx *( basis.phi[i] * ( - (*srcTermIter).second * srcTerm[i] )); } // } } // Loop over Trial Functions if ( fillMatrix ) { /* for(j=0;j < 2; j++) { if (StandardMap->MyGID(row)) { column=OverlapMap->GID(ne+j); jac=basis.wt*basis.dx*( basis.phi[j]/dt*basis.phi[i] +(1.0/(basis.dx*basis.dx))*diffCoef*basis.dphide[j]* basis.dphide[i] + basis.phi[i] * ( (beta+1.0)*basis.phi[j] - 2.0*basis.uu*basis.phi[j]*basis.ddep[id_spec]) ); ierr=A->SumIntoGlobalValues(row, 1, &jac, &column); } } */ } } } } // Apply Dirichlet BC for Temperature problem only (for now); this implies // no-flux across domain boundary for all species. if( getName() == tempFieldName ) { // Insert Boundary Conditions and modify Jacobian and function (F) // U(0)=1 if (MyPID==0) { if ( fillF ) (*rhs)[0]= (*soln)[0] - alpha; if ( fillMatrix ) { int column=0; double jac=1.0; A->ReplaceGlobalValues(0, 1, &jac, &column); column=1; jac=0.0; A->ReplaceGlobalValues(0, 1, &jac, &column); } } // U(1)=1 if ( StandardMap->LID(StandardMap->MaxAllGID()) >= 0 ) { int lastDof = StandardMap->LID(StandardMap->MaxAllGID()); if ( fillF ) (*rhs)[lastDof] = (*soln)[lastDof] - alpha; if ( fillMatrix ) { int row=StandardMap->MaxAllGID(); int column = row; double jac = 1.0; A->ReplaceGlobalValues(row, 1, &jac, &column); jac=0.0; column--; A->ReplaceGlobalValues(row, 1, &jac, &column); } } } // Sync up processors to be safe Comm->Barrier(); A->FillComplete(); #ifdef DEBUG A->Print(cout); if( fillF ) std::cout << "For residual fill :" << std::endl << *rhs << std::endl; if( fillMatrix ) { std::cout << "For jacobian fill :" << std::endl; A->Print(cout); } #endif // Cleanup for( int i = 0; i < numDep; ++i) { delete [] ddep[i]; delete dep[i]; } delete [] srcTerm; return true; }
// Matrix and Residual Fills bool ConvDiff_PDE::evaluate( NOX::Epetra::Interface::Required::FillType flag, const Epetra_Vector * soln, Epetra_Vector * rhs) { if( rhs == 0 ) { std::string msg = "ERROR: ConvDiff_PDE::evaluate : callback appears to be other than a residual fill. Others are not support for this type."; throw msg; } int numDep = depProblems.size(); // Create the overlapped solution and position vectors Epetra_Vector u(*OverlapMap); Epetra_Vector uold(*OverlapMap); std::vector<Epetra_Vector*> dep(numDep); for( int i = 0; i < numDep; ++i) dep[i] = new Epetra_Vector(*OverlapMap); Epetra_Vector xvec(*OverlapMap); // Export Solution to Overlap vector // If the vector to be used in the fill is already in the Overlap form, // we simply need to map on-processor from column-space indices to // OverlapMap indices. Note that the old solution is simply fixed data that // needs to be sent to an OverlapMap (ghosted) vector. The conditional // treatment for the current soution vector arises from use of // FD coloring in parallel. uold.Import(*oldSolution, *Importer, Insert); for( int i = 0; i < numDep; ++i ) (*dep[i]).Import(*( (*(depSolutions.find(depProblems[i]))).second ), *Importer, Insert); xvec.Import(*xptr, *Importer, Insert); if( flag == NOX::Epetra::Interface::Required::FD_Res) // Overlap vector for solution received from FD coloring, so simply reorder // on processor u.Export(*soln, *ColumnToOverlapImporter, Insert); else // Communication to Overlap vector is needed u.Import(*soln, *Importer, Insert); // Declare required variables int OverlapNumMyNodes = OverlapMap->NumMyElements(); int OverlapMinMyNodeGID; if (MyPID==0) OverlapMinMyNodeGID = StandardMap->MinMyGID(); else OverlapMinMyNodeGID = StandardMap->MinMyGID()-1; int row; double * xx = new double[2]; double * uu = new double[2]; double * uuold = new double[2]; std::vector<double*> ddep(numDep); for( int i = 0; i < numDep; ++i) ddep[i] = new double[2]; Basis basis; // Bundle up the dependent variables in the way needed for computing // the source terms of each reaction map<string, double*> depVars; depVars.insert( pair< std::string, double*>(getName(), uu) ); for( int i = 0; i < numDep; ++i ) depVars.insert( pair<string, double*>(myManager->getProblemName(depProblems[i]), ddep[i]) ); // Zero out the objects that will be filled rhs->PutScalar(0.0); // Loop Over # of Finite Elements on Processor for( int ne = 0; ne < OverlapNumMyNodes-1; ++ne ) { // Loop Over Gauss Points for( int gp = 0; gp < 2; ++gp ) { // Get the solution and coordinates at the nodes xx[0]=xvec[ne]; xx[1]=xvec[ne+1]; uu[0] = u[ne]; uu[1] = u[ne+1]; uuold[0] = uold[ne]; uuold[1] = uold[ne+1]; for( int i = 0; i < numDep; ++i ) { ddep[i][0] = (*dep[i])[ne]; ddep[i][1] = (*dep[i])[ne+1]; } // Calculate the basis function and variables at the gauss points basis.getBasis(gp, xx, uu, uuold, ddep); // Loop over Nodes in Element for( int i = 0; i < 2; ++i ) { row = OverlapMap->GID(ne+i); if( StandardMap->MyGID(row) ) { (*rhs)[StandardMap->LID(OverlapMap->GID(ne+i))] += + basis.wt * basis.dx * ( peclet * (basis.duu / basis.dx) * basis.phi[i] + kappa * (1.0/(basis.dx*basis.dx)) * basis.duu * basis.dphide[i] ); } } } } //if( NOX::Epetra::Interface::Required::Residual == flag ) //{ // int lastDof = StandardMap->LID(StandardMap->MaxAllGID()); // std::cout << "\t\"" << myName << "\" u[0] = " << (*soln)[0] // << "\tu[N] = " << (*soln)[lastDof] << std::endl; // std::cout << "\t\"" << myName << "\" RHS[0] = " << (*rhs)[0] // << "\tRHS[N] = " << (*rhs)[lastDof] << std::endl << std::endl; //} // Apply BCs computeHeatFlux( soln ); double bcResidual = bcWeight * (myFlux - depProbPtr->getHeatFlux() ) - (1.0 - bcWeight) * (u[interface_node] - depProbPtr->getInterfaceTemp() ); int lastDof = StandardMap->LID(StandardMap->MaxAllGID()); // "Left" boundary if( LEFT == myInterface ) // this may break in parallel { (*rhs)[0] = bcResidual; (*rhs)[lastDof] = (*soln)[lastDof] - Tright; } // "Right" boundary else { (*rhs)[0] = (*soln)[0] - Tleft; (*rhs)[lastDof] = bcResidual; } // Sync up processors to be safe Comm->Barrier(); A->FillComplete(); #ifdef DEBUG std::cout << "For residual fill :" << std::endl << *rhs << std::endl; #endif // Cleanup for( int i = 0; i < numDep; ++i) { delete [] ddep[i]; delete dep[i]; } delete [] xx ; delete [] uu ; delete [] uuold ; return true; }
bool PelletTransport::evaluate(NOX::Epetra::Interface::Required::FillType fType, const Epetra_Vector* soln, Epetra_Vector* tmp_rhs, Epetra_RowMatrix* tmp_matrix) { if( fType == NOX::Epetra::Interface::Required::Jac ) { cout << "This problem only works for Finite-Difference or Matrix-Free Based Jacobians." << " No analytic Jacobian fill available !!" << endl; throw "Problem ERROR"; } else rhs = new Epetra_Vector(*OverlapMap); // Create the overlapped solution and position vectors Epetra_Vector u(*OverlapMap); Epetra_Vector uold(*OverlapMap); Epetra_Vector xvec(*OverlapNodeMap); // Export Solution to Overlap vector uold.Import(*oldSolution, *Importer, Insert); xvec.Import(*xptr, *nodeImporter, Insert); u.Import(*soln, *Importer, Insert); // Declare required variables int i; int OverlapNumMyNodes = OverlapNodeMap->NumMyElements(); MaterialPropBase::PropData materialProps; // Hard-code use of UO2 for now - RWH 5/14/2007 string fixedType = "UO2"; int OverlapMinMyNodeGID; if (MyPID==0) OverlapMinMyNodeGID = StandardNodeMap->MinMyGID(); else OverlapMinMyNodeGID = StandardNodeMap->MinMyGID()-1; int row1, row2; double term1, term2; double flux1, flux2; double xx[2]; double uu[2*NUMSPECIES]; // Use of the anonymous enum is needed for SGI builds double uuold[2*NUMSPECIES]; Basis basis(NumSpecies); // Zero out the objects that will be filled rhs->PutScalar(0.0); ACTIVE_REGIONS propType; // Loop Over # of Finite Elements on Processor for( int ne = 0; ne < OverlapNumMyNodes - 1; ++ne ) { propType = (ACTIVE_REGIONS) (*elemTypes)[ne]; // Loop Over Gauss Points for( int gp = 0; gp < 2; ++gp ) { // Get the solution and coordinates at the nodes xx[0] = xvec[ne]; xx[1] = xvec[ne+1]; for (int k=0; k<NumSpecies; k++) { uu[NumSpecies * 0 + k] = u[NumSpecies * ne + k]; uu[NumSpecies * 1 + k] = u[NumSpecies * (ne+1) + k]; uuold[NumSpecies * 0 + k] = uold[NumSpecies * ne + k]; uuold[NumSpecies * 1 + k] = uold[NumSpecies * (ne+1) + k]; } // Calculate the basis function at the gauss point basis.getBasis(gp, xx, uu, uuold); MaterialPropFactory::computeProps( propType, basis.uu[0], basis.uu[1], materialProps ); double & rho1 = materialProps.density ; double & k1 = materialProps.k_thermal; double & Cp1 = materialProps.Cp ; double & Qstar1 = materialProps.Qstar ; double & Qdot1 = materialProps.Qdot ; double & Ffunc = materialProps.thermoF ; double & D_diff1 = materialProps.D_diff ; // Loop over Nodes in Element for( i = 0; i < 2; ++i ) { row1=OverlapMap->GID(NumSpecies * (ne+i)); row2=OverlapMap->GID(NumSpecies * (ne+i) + 1); flux1 = -k1*basis.duu[0]/basis.dx; flux2 = -0.5*D_diff1*(basis.duu[1]/basis.dx + basis.uu[1]*Qstar1/(Ffunc*8.3142*basis.uu[0]*basis.uu[0])*basis.duu[0]/basis.dx); term1 = basis.wt*basis.dx*basis.xx*( rho1*Cp1*(basis.uu[0] - basis.uuold[0])/dt * basis.phi[i] - flux1*basis.dphide[i]/basis.dx - Qdot1*basis.phi[i] ); term2 = basis.wt*basis.dx*basis.xx*( 0.5*(basis.uu[1] - basis.uuold[1])/dt * basis.phi[i] - flux2*basis.dphide[i]/basis.dx ); (*rhs)[NumSpecies*(ne+i)] += term1; (*rhs)[NumSpecies*(ne+i)+1] += term2; } } } // Insert Boundary Conditions and modify Jacobian and function (F) // Dirichlet BCs at xminUO2 const double xB = dynamic_cast<const MaterialProp_UO2 &>(MaterialPropFactory::factory().get_model(PelletTransport::UO2)).get_xB(); if (MyPID==0) { // Use no-flux BCs //(*rhs)[0]= (*soln)[0] - 0.6; //(*rhs)[1]= (*soln)[1] - 10.0/3.0; } // Dirichlet BCs at xmaxUO2 if( StandardMap->LID(NumSpecies*(NumGlobalElementsUO2)) >= 0 ) { int lastUO2Dof = StandardMap->LID(NumSpecies*(NumGlobalElementsUO2) + 1); //(*rhs)[lastDof - 1] = (*soln)[lastDof - 1] - 840.0; (*rhs)[lastUO2Dof] = (*soln)[lastUO2Dof] - xB; } // Dirichlet BCs at all He and Clad species variables int lastUO2DofGID = NumSpecies*NumGlobalElementsUO2 + 1; int lastGID = StandardMap->MaxAllGID(); for( int i = lastUO2DofGID; i < lastGID; i+=2 ) if( StandardMap->LID(i) >= 0 ) (*rhs)[StandardMap->LID(i)] = (*soln)[StandardMap->LID(i)] - xB; // Dirichlet BCs at xmaxClad if( StandardMap->LID(StandardMap->MaxAllGID()) >= 0 ) { int lastDof = StandardMap->LID(StandardMap->MaxAllGID()); (*rhs)[lastDof - 1] = (*soln)[lastDof - 1] - 750.0; (*rhs)[lastDof] = (*soln)[lastDof] - xB; } // Sync up processors to be safe Comm->Barrier(); // Do an assemble for overlap nodes tmp_rhs->Export(*rhs, *Importer, Add); delete rhs; return true; }