void BoundaryTangentialLFIntegrator::AssembleRHSElementVect( const FiniteElement &el, ElementTransformation &Tr, Vector &elvect) { int dim = el.GetDim()+1; int dof = el.GetDof(); Vector tangent(dim), Qvec; shape.SetSize(dof); elvect.SetSize(dof); elvect = 0.0; if (dim != 2) mfem_error("These methods make sense only in 2D problems."); const IntegrationRule *ir = IntRule; if (ir == NULL) { int intorder = oa * el.GetOrder() + ob; // <---------- ir = &IntRules.Get(el.GetGeomType(), intorder); } for (int i = 0; i < ir->GetNPoints(); i++) { const IntegrationPoint &ip = ir->IntPoint(i); Tr.SetIntPoint(&ip); const DenseMatrix &Jac = Tr.Jacobian(); tangent(0) = Jac(0,0); tangent(1) = Jac(1,0); Q.Eval(Qvec, Tr, ip); el.CalcShape(ip, shape); add(elvect, ip.weight*(Qvec*tangent), shape, elvect); } }
bool Problem_Interface::computePreconditioner(const Epetra_Vector & x, Epetra_Operator & prec, Teuchos::ParameterList * /*p*/) { START_LOG("preconditioner()", "TrilinosNoxNonlinearSolver"); NonlinearImplicitSystem & sys = _solver->system(); TrilinosPreconditioner<Number> & tpc = dynamic_cast<TrilinosPreconditioner<Number> &>(prec); EpetraMatrix<Number> Jac(dynamic_cast<Epetra_FECrsMatrix *>(tpc.mat()),sys.comm()); EpetraVector<Number> & X_sys = *cast_ptr<EpetraVector<Number> *>(sys.solution.get()); EpetraVector<Number> X_global(*const_cast<Epetra_Vector *>(&x), sys.comm()); // Set the dof maps Jac.attach_dof_map(sys.get_dof_map()); // Use the systems update() to get a good local version of the parallel solution X_global.swap(X_sys); sys.get_dof_map().enforce_constraints_exactly(sys); sys.update(); X_global.swap(X_sys); //----------------------------------------------------------------------------- // if the user has provided both function pointers and objects only the pointer // will be used, so catch that as an error if (_solver->jacobian && _solver->jacobian_object) libmesh_error_msg("ERROR: cannot specify both a function and object to compute the Jacobian!"); if (_solver->matvec && _solver->residual_and_jacobian_object) libmesh_error_msg("ERROR: cannot specify both a function and object to compute the combined Residual & Jacobian!"); if (_solver->jacobian != NULL) _solver->jacobian (*sys.current_local_solution.get(), Jac, sys); else if (_solver->jacobian_object != NULL) _solver->jacobian_object->jacobian (*sys.current_local_solution.get(), Jac, sys); else if (_solver->matvec != NULL) _solver->matvec (*sys.current_local_solution.get(), NULL, &Jac, sys); else if (_solver->residual_and_jacobian_object != NULL) _solver->residual_and_jacobian_object->residual_and_jacobian (*sys.current_local_solution.get(), NULL, &Jac, sys); else libmesh_error_msg("Error! Unable to compute residual and/or Jacobian!"); Jac.close(); X_global.close(); tpc.compute(); STOP_LOG("preconditioner()", "TrilinosNoxNonlinearSolver"); return true; }
// XXX: Jac(i, 6) or column #7 is all zero ! void PointSolver2::prepareMatrices () { Jac = Eigen::MatrixXd::Zero (ipoints.size(), 7); Pcorrect = Eigen::VectorXd::Zero (7); pointErrs = Eigen::VectorXd::Zero (ipoints.size()); for (int ip=0; ip<ipoints.size(); ip++) { pointErrs [ip] = ipoints[ip].lineDistance; Point2 curpt = ipoints[ip].coord; pscalar jacobianPt[7]; LineSegment2D &line = visibleLines[ipoints[ip].nearestLine]; line.errorJacobian(curpt, jacobianPt); for (int n=0; n<7; n++) { Jac(ip, n) = jacobianPt[n]; } continue; } // std::cout << pointErrs << std::endl; // std::cout << Jac << std::endl; }
//--------------------------------------------------------------- // this function is called by PETSc to evaluate the Jacobian at X PetscErrorCode __libmesh_petsc_snes_jacobian (SNES snes, Vec x, Mat *jac, Mat *pc, MatStructure *msflag, void *ctx) { START_LOG("jacobian()", "PetscNonlinearSolver"); PetscErrorCode ierr=0; libmesh_assert(ctx); PetscNonlinearSolver<Number>* solver = static_cast<PetscNonlinearSolver<Number>*> (ctx); // Get the current iteration number from the snes object, // store it in the PetscNonlinearSolver object for possible use // by the user's Jacobian function. { PetscInt n_iterations = 0; ierr = SNESGetIterationNumber(snes, &n_iterations); CHKERRABORT(solver->comm().get(),ierr); solver->set_current_nonlinear_iteration_number( static_cast<unsigned>(n_iterations) ); } NonlinearImplicitSystem &sys = solver->system(); PetscMatrix<Number> PC(*pc, sys.comm()); PetscMatrix<Number> Jac(*jac, sys.comm()); PetscVector<Number>& X_sys = *libmesh_cast_ptr<PetscVector<Number>*>(sys.solution.get()); PetscMatrix<Number>& Jac_sys = *libmesh_cast_ptr<PetscMatrix<Number>*>(sys.matrix); PetscVector<Number> X_global(x, sys.comm()); // Set the dof maps PC.attach_dof_map(sys.get_dof_map()); Jac.attach_dof_map(sys.get_dof_map()); // Use the systems update() to get a good local version of the parallel solution X_global.swap(X_sys); Jac.swap(Jac_sys); sys.get_dof_map().enforce_constraints_exactly(sys); sys.update(); X_global.swap(X_sys); Jac.swap(Jac_sys); PC.zero(); //----------------------------------------------------------------------------- // if the user has provided both function pointers and objects only the pointer // will be used, so catch that as an error if (solver->jacobian && solver->jacobian_object) { libMesh::err << "ERROR: cannot specifiy both a function and object to compute the Jacobian!" << std::endl; libmesh_error(); } if (solver->matvec && solver->residual_and_jacobian_object) { libMesh::err << "ERROR: cannot specifiy both a function and object to compute the combined Residual & Jacobian!" << std::endl; libmesh_error(); } //----------------------------------------------------------------------------- if (solver->jacobian != NULL) solver->jacobian (*sys.current_local_solution.get(), PC, sys); else if (solver->jacobian_object != NULL) solver->jacobian_object->jacobian (*sys.current_local_solution.get(), PC, sys); else if (solver->matvec != NULL) solver->matvec (*sys.current_local_solution.get(), NULL, &PC, sys); else if (solver->residual_and_jacobian_object != NULL) solver->residual_and_jacobian_object->residual_and_jacobian (*sys.current_local_solution.get(), NULL, &PC, sys); else libmesh_error(); PC.close(); Jac.close(); X_global.close(); *msflag = SAME_NONZERO_PATTERN; STOP_LOG("jacobian()", "PetscNonlinearSolver"); return ierr; }
bool ASMs1D::integrate (Integrand& integrand, int lIndex, GlobalIntegral& glInt, const TimeDomain& time) { if (!curv) return true; // silently ignore empty patches // Integration of boundary point FiniteElement fe(curv->order()); size_t iel = 0; switch (lIndex) { case 1: fe.xi = -1.0; fe.u = curv->startparam(); break; case 2: fe.xi = 1.0; fe.u = curv->endparam(); iel = nel-1; break; default: return false; } std::map<char,size_t>::const_iterator iit = firstBp.find(lIndex); fe.iGP = iit == firstBp.end() ? 0 : iit->second; fe.iel = MLGE[iel]; if (fe.iel < 1) return true; // zero-length element // Set up control point coordinates for current element if (!this->getElementCoordinates(fe.Xn,1+iel)) return false; if (integrand.getIntegrandType() & Integrand::ELEMENT_CORNERS) this->getElementEnds(iel+curv->order(),fe.XC); if (integrand.getIntegrandType() & Integrand::NODAL_ROTATIONS) { this->getElementNodalRotations(fe.Tn,iel); if (!elmCS.empty()) fe.Te = elmCS[iel]; } // Initialize element matrices LocalIntegral* A = integrand.getLocalIntegral(fe.N.size(),fe.iel,true); bool ok = integrand.initElementBou(MNPC[iel],*A); Vec3 normal; // Evaluate basis functions and corresponding derivatives if (integrand.getIntegrandType() & Integrand::NO_DERIVATIVES) this->extractBasis(fe.u,fe.N); else { // Compute basis function derivatives Matrix dNdu, Jac; this->extractBasis(fe.u,fe.N,dNdu); utl::Jacobian(Jac,fe.dNdX,fe.Xn,dNdu); // Set up the normal vector if (lIndex == 1) normal.x = -copysign(1.0,Jac(1,1)); else normal.x = copysign(1.0,Jac(1,1)); } // Cartesian coordinates of current integration point Vec4 X(fe.Xn*fe.N,time.t); // Evaluate the integrand and accumulate element contributions if (ok && !integrand.evalBou(*A,fe,time,X,normal)) ok = false; // Assembly of global system integral if (ok && !glInt.assemble(A->ref(),fe.iel)) ok = false; A->destruct(); return ok; }
void Triangle::setdetJ(){ M_detJ = Jac().determinant(); }
int main() { #ifdef _AUTODIFF #ifdef FAD const int dim = 3; const int nstate = dim+2; const int nphi = 6; // emulating state variables TPZVec<TPZDiffMatrix<REAL> > Ai, Tau; TPZVec<TPZVec<REAL> > TauDiv; TPZVec<TPZDiffMatrix<REAL> > TaudDiv; /*char ArtDiff[32]="LS";*/ TPZArtDiffType artDiffType = LeastSquares_AD; TPZFMatrix dsol(dim,nstate); TPZFMatrix dphi(dim,nphi); TPZVec<REAL> phi(nphi); TPZVec<REAL> sol(nstate); TPZVec<FADREAL> FADsol(nstate); TPZVec<FADREAL> FADdsol(nstate*dim); TPZVec<TPZVec<FADREAL> > FADTauDiv; // generating data TPZArtDiff ArtDiff(artDiffType, 1.4); //solution sol[0]=2.; sol[1]=3.; sol[2]=5.; sol[3]=7.; sol[4]=11.; //phi phi[0]=2.3; phi[1]=3.5; phi[2]=5.7; phi[3]=7.11; phi[4]=11.13; phi[5]=13.17; //dphi int i; int j; for(i=0;i<dim;i++) for(j=0;j<nphi;j++) dphi(i,j)=45.8*i-3.2*j; // any choice //dsol for(i=0;i<dim;i++) for(j=0;j<nstate;j++) dsol(i,j)=49.8*i-3.1*j; // any choice int k, l; //FADsol for(i=0;i<nstate;i++) { FADsol[i]=sol[i]; FADsol[i].diff(0,nphi*nstate); FADsol[i].fastAccessDx(0)=0.; for(j=0;j<nphi;j++)FADsol[i].fastAccessDx(i+j*nstate)=phi[j]; } /* FADREAL teste; for(i=0;i<FADsol.NElements();i++)teste+=FADsol[i]; cout << "\n\nFADsol\n" << teste; cout << "\n\nphi\n" << phi; */ //FADdSol for(k=0;k<dim;k++) for(i=0;i<nstate;i++) { FADdsol[k+i*dim]=dsol(k,i); FADdsol[k+i*dim].diff(0,nphi*nstate); FADdsol[k+i*dim].fastAccessDx(0)=0.; for(j=0;j<nphi;j++) FADdsol[k+i*dim].fastAccessDx(i+j*nstate)=dphi(k,j); } /* cout << "\n\nFADdsol\n"; teste=0; for(i=0;i<FADdsol.NElements();i+=3)teste+=FADdsol[i]; cout << teste << endl; teste=0; for(i=1;i<FADdsol.NElements();i+=3)teste+=FADdsol[i]; cout << teste << endl; teste=0; for(i=2;i<FADdsol.NElements();i+=3)teste+=FADdsol[i]; cout << teste << endl; //cout << "\n\nFADdsol\n" << FADdsol; cout << "\n\ndphi\n" << dphi; */ TPZFMatrix Jac(dim,dim,1.); ArtDiff.PrepareFastDiff(dim,Jac, sol, dsol, dphi, TauDiv, &TaudDiv); ArtDiff.PrepareFastDiff(dim, Jac, FADsol, FADdsol, FADTauDiv); cout << "\n\nFADTauDiv\n" << FADTauDiv; cout << "\n\nTauDiv\n" << TauDiv; cout << "\n\nTaudDiv\n" << TaudDiv; #endif #endif return 0; }
void MappingExtrapolate::v_CorrectPressureBCs( const Array<OneD, NekDouble> &pressure) { if(m_HBCdata.num_elements()>0) { int cnt, n; int physTot = m_fields[0]->GetTotPoints(); int nvel = m_fields.num_elements()-1; Array<OneD, NekDouble> Vals; // Remove previous correction for(cnt = n = 0; n < m_PBndConds.num_elements(); ++n) { if(m_PBndConds[n]->GetUserDefined() == "H") { int nq = m_PBndExp[n]->GetNcoeffs(); Vmath::Vsub(nq, &(m_PBndExp[n]->GetCoeffs()[0]), 1, &(m_bcCorrection[cnt]), 1, &(m_PBndExp[n]->UpdateCoeffs()[0]), 1); cnt += nq; } } // Calculate new correction Array<OneD, NekDouble> Jac(physTot, 0.0); m_mapping->GetJacobian(Jac); Array<OneD, Array<OneD, NekDouble> > correction(nvel); Array<OneD, Array<OneD, NekDouble> > gradP(nvel); Array<OneD, Array<OneD, NekDouble> > wk(nvel); Array<OneD, Array<OneD, NekDouble> > wk2(nvel); for (int i=0; i<nvel; i++) { wk[i] = Array<OneD, NekDouble> (physTot, 0.0); gradP[i] = Array<OneD, NekDouble> (physTot, 0.0); correction[i] = Array<OneD, NekDouble> (physTot, 0.0); } // Calculate G(p) for(int i = 0; i < nvel; ++i) { m_fields[0]->PhysDeriv(MultiRegions::DirCartesianMap[i], pressure, gradP[i]); if(m_fields[0]->GetWaveSpace()) { m_fields[0]->HomogeneousBwdTrans(gradP[i], wk[i]); } else { Vmath::Vcopy(physTot, gradP[i], 1, wk[i], 1); } } m_mapping->RaiseIndex(wk, correction); // G(p) // alpha*J*(G(p)) if (!m_mapping->HasConstantJacobian()) { for(int i = 0; i < nvel; ++i) { Vmath::Vmul(physTot, correction[i], 1, Jac, 1, correction[i], 1); } } for(int i = 0; i < nvel; ++i) { Vmath::Smul(physTot, m_pressureRelaxation, correction[i], 1, correction[i], 1); } if(m_pressure->GetWaveSpace()) { for(int i = 0; i < nvel; ++i) { m_pressure->HomogeneousFwdTrans(correction[i], correction[i]); } } // p_i - alpha*J*div(G(p)) for (int i = 0; i < nvel; ++i) { Vmath::Vsub(physTot, gradP[i], 1, correction[i], 1, correction[i], 1); } // Get value at boundary and calculate Inner product StdRegions::StdExpansionSharedPtr Pbc; StdRegions::StdExpansionSharedPtr elmt; Array<OneD, Array<OneD, const NekDouble> > correctionElmt(m_bnd_dim); Array<OneD, Array<OneD, NekDouble> > BndValues(m_bnd_dim); for(int i = 0; i < m_bnd_dim; i++) { BndValues[i] = Array<OneD, NekDouble> (m_pressureBCsMaxPts,0.0); } for(int j = 0 ; j < m_HBCdata.num_elements() ; j++) { /// Casting the boundary expansion to the specific case Pbc = boost::dynamic_pointer_cast<StdRegions::StdExpansion> (m_PBndExp[m_HBCdata[j].m_bndryID] ->GetExp(m_HBCdata[j].m_bndElmtID)); /// Picking up the element where the HOPBc is located elmt = m_pressure->GetExp(m_HBCdata[j].m_globalElmtID); /// Assigning for(int i = 0; i < m_bnd_dim; i++) { correctionElmt[i] = correction[i] + m_HBCdata[j].m_physOffset; } Vals = m_bcCorrection + m_HBCdata[j].m_coeffOffset; // Getting values on the edge and filling the correction switch(m_pressure->GetExpType()) { case MultiRegions::e2D: case MultiRegions::e3DH1D: { elmt->GetEdgePhysVals(m_HBCdata[j].m_elmtTraceID, Pbc, correctionElmt[0], BndValues[0]); elmt->GetEdgePhysVals(m_HBCdata[j].m_elmtTraceID, Pbc, correctionElmt[1], BndValues[1]); // InnerProduct Pbc->NormVectorIProductWRTBase(BndValues[0], BndValues[1], Vals); } break; case MultiRegions::e3D: { elmt->GetFacePhysVals(m_HBCdata[j].m_elmtTraceID, Pbc, correctionElmt[0], BndValues[0]); elmt->GetFacePhysVals(m_HBCdata[j].m_elmtTraceID, Pbc, correctionElmt[1], BndValues[1]); elmt->GetFacePhysVals(m_HBCdata[j].m_elmtTraceID, Pbc, correctionElmt[2], BndValues[2]); Pbc->NormVectorIProductWRTBase(BndValues[0], BndValues[1], BndValues[2], Vals); } break; default: ASSERTL0(0,"Dimension not supported"); break; } } // Apply new correction for(cnt = n = 0; n < m_PBndConds.num_elements(); ++n) { if(m_PBndConds[n]->GetUserDefined() == "H") { int nq = m_PBndExp[n]->GetNcoeffs(); Vmath::Vadd(nq, &(m_PBndExp[n]->GetCoeffs()[0]), 1, &(m_bcCorrection[cnt]), 1, &(m_PBndExp[n]->UpdateCoeffs()[0]), 1); cnt += nq; } } } }
void MappingExtrapolate::v_CalcNeumannPressureBCs( const Array<OneD, const Array<OneD, NekDouble> > &fields, const Array<OneD, const Array<OneD, NekDouble> > &N, NekDouble kinvis) { if (m_mapping->HasConstantJacobian() && !m_implicitViscous) { Extrapolate::v_CalcNeumannPressureBCs( fields, N, kinvis); } else { int physTot = m_fields[0]->GetTotPoints(); int nvel = m_fields.num_elements()-1; Array<OneD, NekDouble> Pvals; StdRegions::StdExpansionSharedPtr Pbc; StdRegions::StdExpansionSharedPtr elmt; Array<OneD, Array<OneD, const NekDouble> > Velocity(m_bnd_dim); Array<OneD, Array<OneD, const NekDouble> > Advection(m_bnd_dim); // Get transformation Jacobian Array<OneD, NekDouble> Jac(physTot,0.0); m_mapping->GetJacobian(Jac); // Declare variables Array<OneD, Array<OneD, NekDouble> > BndValues(m_bnd_dim); Array<OneD, Array<OneD, NekDouble> > Q(m_bnd_dim); Array<OneD, Array<OneD, NekDouble> > Q_field(nvel); Array<OneD, Array<OneD, NekDouble> > fields_new(nvel); Array<OneD, Array<OneD, NekDouble> > N_new(m_bnd_dim); // Temporary variables Array<OneD, NekDouble> tmp(physTot,0.0); Array<OneD, NekDouble> tmp2(physTot,0.0); for(int i = 0; i < m_bnd_dim; i++) { BndValues[i] = Array<OneD, NekDouble> (m_pressureBCsMaxPts,0.0); Q[i] = Array<OneD, NekDouble> (m_pressureBCsElmtMaxPts,0.0); N_new[i] = Array<OneD, NekDouble> (physTot,0.0); } for(int i = 0; i < nvel; i++) { Q_field[i] = Array<OneD, NekDouble> (physTot,0.0); fields_new[i] = Array<OneD, NekDouble> (physTot,0.0); } // Multiply convective terms by Jacobian for(int i = 0; i < m_bnd_dim; i++) { if (m_fields[0]->GetWaveSpace()) { m_fields[0]->HomogeneousBwdTrans(N[i],N_new[i]); } else { Vmath::Vcopy(physTot, N[i], 1, N_new[i], 1); } Vmath::Vmul(physTot, Jac, 1, N_new[i], 1, N_new[i], 1); if (m_fields[0]->GetWaveSpace()) { m_fields[0]->HomogeneousFwdTrans(N_new[i],N_new[i]); } } // Get velocity in physical space for(int i = 0; i < nvel; i++) { if (m_fields[0]->GetWaveSpace()) { m_fields[0]->HomogeneousBwdTrans(fields[i],fields_new[i]); } else { Vmath::Vcopy(physTot, fields[i], 1, fields_new[i], 1); } } // Calculate appropriate form of the CurlCurl operator m_mapping->CurlCurlField(fields_new, Q_field, m_implicitViscous); // If viscous terms are treated explicitly, // add grad(U/J \dot grad J) to CurlCurl if ( !m_implicitViscous) { m_mapping->DotGradJacobian(fields_new, tmp); Vmath::Vdiv(physTot, tmp, 1, Jac, 1, tmp, 1); bool wavespace = m_fields[0]->GetWaveSpace(); m_fields[0]->SetWaveSpace(false); for(int i = 0; i < m_bnd_dim; i++) { m_fields[0]->PhysDeriv(MultiRegions::DirCartesianMap[i], tmp, tmp2); Vmath::Vadd(physTot, Q_field[i], 1, tmp2, 1, Q_field[i], 1); } m_fields[0]->SetWaveSpace(wavespace); } // Multiply by Jacobian and convert to wavespace (if necessary) for(int i = 0; i < m_bnd_dim; i++) { Vmath::Vmul(physTot, Jac, 1, fields_new[i], 1, fields_new[i], 1); Vmath::Vmul(physTot, Jac, 1, Q_field[i] , 1, Q_field[i] , 1); if (m_fields[0]->GetWaveSpace()) { m_fields[0]->HomogeneousFwdTrans(fields_new[i],fields_new[i]); m_fields[0]->HomogeneousFwdTrans(Q_field[i],Q_field[i]); } } for(int j = 0 ; j < m_HBCdata.num_elements() ; j++) { /// Casting the boundary expansion to the specific case Pbc = boost::dynamic_pointer_cast<StdRegions::StdExpansion> (m_PBndExp[m_HBCdata[j].m_bndryID] ->GetExp(m_HBCdata[j].m_bndElmtID)); /// Picking up the element where the HOPBc is located elmt = m_pressure->GetExp(m_HBCdata[j].m_globalElmtID); /// Assigning for(int i = 0; i < m_bnd_dim; i++) { Velocity[i] = fields_new[i] + m_HBCdata[j].m_physOffset; Advection[i] = N_new[i] + m_HBCdata[j].m_physOffset; Q[i] = Q_field[i] + m_HBCdata[j].m_physOffset; } // Mounting advection component into the high-order condition for(int i = 0; i < m_bnd_dim; i++) { MountHOPBCs(m_HBCdata[j].m_ptsInElmt,kinvis,Q[i],Advection[i]); } Pvals = m_pressureHBCs[0] + m_HBCdata[j].m_coeffOffset; // Getting values on the edge and filling the pressure boundary // expansion and the acceleration term. Multiplication by the // normal is required switch(m_pressure->GetExpType()) { case MultiRegions::e2D: case MultiRegions::e3DH1D: { elmt->GetEdgePhysVals(m_HBCdata[j].m_elmtTraceID, Pbc, Q[0], BndValues[0]); elmt->GetEdgePhysVals(m_HBCdata[j].m_elmtTraceID, Pbc, Q[1], BndValues[1]); // InnerProduct Pbc->NormVectorIProductWRTBase(BndValues[0], BndValues[1], Pvals); } break; case MultiRegions::e3DH2D: { if(m_HBCdata[j].m_elmtTraceID == 0) { (m_PBndExp[m_HBCdata[j].m_bndryID]->UpdateCoeffs() + m_PBndExp[m_HBCdata[j].m_bndryID] ->GetCoeff_Offset( m_HBCdata[j].m_bndElmtID))[0] = -1.0*Q[0][0]; } else if (m_HBCdata[j].m_elmtTraceID == 1) { (m_PBndExp[m_HBCdata[j].m_bndryID]->UpdateCoeffs() + m_PBndExp[m_HBCdata[j].m_bndryID] ->GetCoeff_Offset( m_HBCdata[j].m_bndElmtID))[0] = Q[0][m_HBCdata[j].m_ptsInElmt-1]; } else { ASSERTL0(false, "In the 3D homogeneous 2D approach BCs edge " "ID can be just 0 or 1 "); } } break; case MultiRegions::e3D: { elmt->GetFacePhysVals(m_HBCdata[j].m_elmtTraceID, Pbc, Q[0], BndValues[0]); elmt->GetFacePhysVals(m_HBCdata[j].m_elmtTraceID, Pbc, Q[1], BndValues[1]); elmt->GetFacePhysVals(m_HBCdata[j].m_elmtTraceID, Pbc, Q[2], BndValues[2]); Pbc->NormVectorIProductWRTBase(BndValues[0], BndValues[1], BndValues[2], Pvals); } break; default: ASSERTL0(0,"Dimension not supported"); break; } } } // If pressure terms are treated implicitly, we need to multiply // by the relaxation parameter, and zero the correction term if (m_implicitPressure) { Vmath::Smul(m_pressureHBCs[0].num_elements(), m_pressureRelaxation, m_pressureHBCs[0], 1, m_pressureHBCs[0], 1); } m_bcCorrection = Array<OneD, NekDouble> (m_pressureHBCs[0].num_elements(), 0.0); }