sparse BuildAdvection(const DataStructure& Domain, double velocity) { int Npts = Domain.GetNpts(); sparse Advection(Npts,Npts,3*Npts); int nnz = 0; if(velocity > .0) for(int i = 0; i < Npts; i++) { Advection.Val(nnz) = - 1.0 / hx - 1.0 / hy; Advection.Row(nnz) = i; Advection.Col(nnz) = i; nnz++; if(Domain(Domain[i],Domain(i)+1) != -4) { Advection.Val(nnz) = 1.0 / hx; Advection.Row(nnz) = i; Advection.Col(nnz) = Domain(Domain[i],Domain(i)+1); nnz++; } else { Advection.Val(nnz) = 1.0 / hx; Advection.Row(nnz) = i; Advection.Col(nnz) = i; nnz++; } if(Domain(Domain[i] + 1,Domain(i)) != -3) { Advection.Val(nnz) = 1.0/hy; Advection.Row(nnz) = i; Advection.Col(nnz) = Domain(Domain[i]+1,Domain(i)); nnz++; } else { Advection.Val(nnz) = 1.0/hy; Advection.Row(nnz) = i; Advection.Col(nnz) = i; nnz++; } } else for(int i = 0; i < Npts; i++) { Advection.Val(nnz) = 1.0 / hx + 1.0 / hy; Advection.Row(nnz) = i; Advection.Col(nnz) = i; nnz++; if(Domain(Domain[i],Domain(i) - 1) != -2) { Advection.Val(nnz) = - 1.0 / hx; Advection.Row(nnz) = i; Advection.Col(nnz) = Domain(Domain[i],Domain(i)-1); nnz++; } else { Advection.Val(nnz) = - 1.0 / hx; Advection.Row(nnz) = i; Advection.Col(nnz) = i; nnz++; } if(Domain(Domain[i]-1,Domain(i)) != -1) { Advection.Val(nnz) = - 1.0/hy; Advection.Row(nnz) = i; Advection.Col(nnz) = Domain(Domain[i]-1,Domain(i)); nnz++; } else { Advection.Val(nnz) = - 1.0/hy; Advection.Row(nnz) = i; Advection.Col(nnz) = i; nnz++; } } Advection.CreateSparse(); return Advection; }
sparse AssembleAdvection(DataStructure& Data, double velocity, char* BCType) { /* Dirichlet BC is implemented inefficiently here */ int Nverts = Data.GetNverts(), nnz = 0, NNZMAX = 0, nBC = 0, uBC; bool DirichletIsTrue = false; if(!strcmp(BCType,"Dirichlet")) DirichletIsTrue = true; for(int i = 0; i < Data.GetNverts(); i++) NNZMAX += Data.GetNeigh(i,0); sparse Advection(Nverts,Nverts,2*NNZMAX); ifstream file; if(DirichletIsTrue) { file.open("Dirichlet.dat"); file >> nBC >> uBC; } vector BoundPts(nBC); if(DirichletIsTrue) for(int i = 0; i < nBC; i++) file >> BoundPts(i); file.close(); for(int i = 0; i < Nverts; i++) { int n = Data.GetNeigh(i,0); double Area_C = .0; for(int k = 1; k <= n; k++) Area_C += Data.GetArea(Data.GetNeigh(i,k)); Area_C *= 1.0/3.0; for(int j = 1; j <= n; j++) { double x[3], y[3]; vector nodes(3); for(int k = 0; k < 3; k++) nodes(k) = Data.GetTris(Data.GetNeigh(i,j),k); int index1 = find(nodes,i), index2 = 1, index3 = 2; if(index1 == 1) { index2 = 2; index3 = 0; } if(index1 == 2) { index2 = 0; index3 = 1; } x[0] = Data.GetVerts(nodes(index1),0); y[0] = Data.GetVerts(nodes(index1),1); x[1] = Data.GetVerts(nodes(index2),0); y[1] = Data.GetVerts(nodes(index2),1); x[2] = Data.GetVerts(nodes(index3),0); y[2] = Data.GetVerts(nodes(index3),1); bool IsBoundary1 = CheckBC(nodes(index1),BoundPts), IsBoundary2 = CheckBC(nodes(index2),BoundPts), IsBoundary3 = CheckBC(nodes(index3),BoundPts); double delta_x1 = x[2]/3.0 - x[1]/6.0 - x[0]/6.0, delta_y1 = y[2]/3.0 - y[1]/6.0 - y[0]/6.0, delta_x2 = x[2]/6.0 - x[1]/3.0 + x[0]/6.0, delta_y2 = y[2]/6.0 - y[1]/3.0 + y[0]/6.0; double qf1 = velocity * (delta_y1 - delta_x1), qf2 = velocity * (delta_y2 - delta_x2); if(qf1 > 0) { Advection.Row(nnz) = i; Advection.Col(nnz) = Data.GetTris(Data.GetNeigh(i,j),index1); if(IsBoundary1) Advection.Val(nnz) = .0; else Advection.Val(nnz) = - qf1 / Area_C; nnz++; } else { Advection.Row(nnz) = i; Advection.Col(nnz) = Data.GetTris(Data.GetNeigh(i,j),index2); if(IsBoundary2) Advection.Val(nnz) = .0; else Advection.Val(nnz) = - qf1 / Area_C; nnz++; } if(qf2 > 0) { Advection.Row(nnz) = i; Advection.Col(nnz) = Data.GetTris(Data.GetNeigh(i,j),index1); if(IsBoundary1) Advection.Val(nnz) = .0; else Advection.Val(nnz) = - qf2 / Area_C; nnz++; } else { Advection.Row(nnz) = i; Advection.Col(nnz) = Data.GetTris(Data.GetNeigh(i,j),index3); if(IsBoundary3) Advection.Val(nnz) = .0; else Advection.Val(nnz) = - qf2 / Area_C; nnz++; } } } Advection.CreateSparse(); return Advection; }
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); }