namespace Utilities { ModuleKey ProcessEquiSpacedOutput::className = GetModuleFactory().RegisterCreatorFunction( ModuleKey(eProcessModule, "equispacedoutput"), ProcessEquiSpacedOutput::create, "Write data as equi-spaced output using simplices to represent the data for connecting points"); ProcessEquiSpacedOutput::ProcessEquiSpacedOutput(FieldSharedPtr f) : ProcessModule(f) { f->m_setUpEquiSpacedFields = true; m_config["tetonly"] = ConfigOption(true, "NotSet", "Only process tetrahedral elements"); m_config["modalenergy"] = ConfigOption(true,"NotSet","Write output as modal energy"); } ProcessEquiSpacedOutput::~ProcessEquiSpacedOutput() { } void ProcessEquiSpacedOutput::Process(po::variables_map &vm) { SetupEquiSpacedField(); } void ProcessEquiSpacedOutput::SetupEquiSpacedField(void) { if(m_f->m_verbose) { cout << "Interpolating fields to equispaced" << endl; } int coordim = m_f->m_exp[0]->GetCoordim(0); int shapedim = m_f->m_exp[0]->GetExp(0)->GetShapeDimension(); int npts = m_f->m_exp[0]->GetTotPoints(); Array<OneD, Array<OneD, NekDouble> > coords(3); int nel = m_f->m_exp[0]->GetExpSize(); // set up the number of points in each element int newpoints; int newtotpoints = 0; Array<OneD,int> conn; int prevNcoeffs = 0; int prevNpoints = 0; int cnt = 0; // identify face 1 connectivity for prisms map<int,StdRegions::Orientation > face0orient; set<int> prismorient; LocalRegions::ExpansionSharedPtr e; // prepare PtsField vector<std::string> fieldNames; vector<int> ppe; vector<Array<OneD, int> > ptsConn; int nfields; for(int i = 0; i < nel; ++i) { e = m_f->m_exp[0]->GetExp(i); if(e->DetShapeType() == LibUtilities::ePrism) { StdRegions::Orientation forient = e->GetForient(0); int fid = e->GetGeom()->GetFid(0); if(face0orient.count(fid)) { // face 1 meeting face 1 so reverse this id prismorient.insert(i); } else { // just store if Dir 1 is fwd or bwd if((forient == StdRegions::eDir1BwdDir1_Dir2FwdDir2) || (forient == StdRegions::eDir1BwdDir1_Dir2BwdDir2) || (forient == StdRegions::eDir1BwdDir2_Dir2FwdDir1) || (forient == StdRegions::eDir1BwdDir2_Dir2BwdDir1)) { face0orient[fid] = StdRegions::eBwd; } else { face0orient[fid] = StdRegions::eFwd; } } } } for(int i = 0; i < nel; ++i) { e = m_f->m_exp[0]->GetExp(i); if(e->DetShapeType() == LibUtilities::ePrism) { int fid = e->GetGeom()->GetFid(2); // check to see if face 2 meets face 1 if(face0orient.count(fid)) { // check to see how face 2 is orientated StdRegions::Orientation forient2 = e->GetForient(2); StdRegions::Orientation forient0 = face0orient[fid]; // If dir 1 or forient2 is bwd then check agains // face 1 value if((forient2 == StdRegions::eDir1BwdDir1_Dir2FwdDir2) || (forient2 == StdRegions::eDir1BwdDir1_Dir2BwdDir2) || (forient2 == StdRegions::eDir1BwdDir2_Dir2FwdDir1) || (forient2 == StdRegions::eDir1BwdDir2_Dir2BwdDir1)) { if(forient0 == StdRegions::eFwd) { prismorient.insert(i); } } else { if(forient0 == StdRegions::eBwd) { prismorient.insert(i); } } } } } for(int i = 0; i < nel; ++i) { e = m_f->m_exp[0]->GetExp(i); if(m_config["tetonly"].m_beenSet) { if(m_f->m_exp[0]->GetExp(i)->DetShapeType() != LibUtilities::eTetrahedron) { continue; } } ppe.push_back(newpoints); newtotpoints += newpoints; switch(e->DetShapeType()) { case LibUtilities::eSegment: { int npoints0 = e->GetBasis(0)->GetNumPoints(); newpoints = LibUtilities::StdSegData:: getNumberOfCoefficients(npoints0); } break; case LibUtilities::eTriangle: { int np0 = e->GetBasis(0)->GetNumPoints(); int np1 = e->GetBasis(1)->GetNumPoints(); int np = max(np0,np1); newpoints = LibUtilities::StdTriData:: getNumberOfCoefficients(np,np); } break; case LibUtilities::eQuadrilateral: { int np0 = e->GetBasis(0)->GetNumPoints(); int np1 = e->GetBasis(1)->GetNumPoints(); int np = max(np0,np1); newpoints = LibUtilities::StdQuadData:: getNumberOfCoefficients(np,np); } break; case LibUtilities::eTetrahedron: { int np0 = e->GetBasis(0)->GetNumPoints(); int np1 = e->GetBasis(1)->GetNumPoints(); int np2 = e->GetBasis(2)->GetNumPoints(); int np = max(np0,max(np1,np2)); newpoints = LibUtilities::StdTetData:: getNumberOfCoefficients(np,np,np); } break; case LibUtilities::ePrism: { int np0 = e->GetBasis(0)->GetNumPoints(); int np1 = e->GetBasis(1)->GetNumPoints(); int np2 = e->GetBasis(2)->GetNumPoints(); int np = max(np0,max(np1,np2)); newpoints = LibUtilities::StdPrismData:: getNumberOfCoefficients(np,np,np); } break; case LibUtilities::ePyramid: { int np0 = e->GetBasis(0)->GetNumPoints(); int np1 = e->GetBasis(1)->GetNumPoints(); int np2 = e->GetBasis(2)->GetNumPoints(); int np = max(np0,max(np1,np2)); newpoints = LibUtilities::StdPyrData:: getNumberOfCoefficients(np,np,np); } break; case LibUtilities::eHexahedron: { int np0 = e->GetBasis(0)->GetNumPoints(); int np1 = e->GetBasis(1)->GetNumPoints(); int np2 = e->GetBasis(2)->GetNumPoints(); int np = max(np0,max(np1,np2)); newpoints = LibUtilities::StdPyrData:: getNumberOfCoefficients(np,np,np); } break; default: { ASSERTL0(false,"Points not known"); } } if(e->DetShapeType() == LibUtilities::ePrism) { bool standard = true; if(prismorient.count(i)) { standard = false; // reverse direction } e->GetSimplexEquiSpacedConnectivity(conn,standard); } else { if((prevNcoeffs != e->GetNcoeffs()) || (prevNpoints != e->GetTotPoints())) { prevNcoeffs = e->GetNcoeffs(); prevNpoints = e->GetTotPoints(); e->GetSimplexEquiSpacedConnectivity(conn); } } Array<OneD, int> newconn(conn.num_elements()); for(int j = 0; j < conn.num_elements(); ++j) { newconn[j] = conn[j] + cnt; } ptsConn.push_back(newconn); cnt += newpoints; } if(m_f->m_fielddef.size()) { nfields = m_f->m_exp.size(); } else // just the mesh points { nfields = 0; } Array<OneD, Array<OneD, NekDouble> > pts(nfields + coordim); for(int i = 0; i < nfields + coordim; ++i) { pts[i] = Array<OneD, NekDouble>(newtotpoints); } // Interpolate coordinates for(int i = 0; i < coordim; ++i) { coords[i] = Array<OneD, NekDouble>(npts); } for(int i = coordim; i < 3; ++i) { coords[i] = NullNekDouble1DArray; } m_f->m_exp[0]->GetCoords(coords[0],coords[1],coords[2]); int nq1 = m_f->m_exp[0]->GetTotPoints(); Array<OneD, NekDouble> x1(nq1); Array<OneD, NekDouble> y1(nq1); Array<OneD, NekDouble> z1(nq1); m_f->m_exp[0]->GetCoords(x1, y1, z1); Array<OneD, NekDouble> tmp; for(int n = 0; n < coordim; ++n) { cnt = 0; int cnt1 = 0; for(int i = 0; i < nel; ++i) { m_f->m_exp[0]->GetExp(i)->PhysInterpToSimplexEquiSpaced( coords[n] + cnt, tmp = pts[n] + cnt1); cnt1 += ppe[i]; cnt += m_f->m_exp[0]->GetExp(i)->GetTotPoints(); } } if(m_f->m_fielddef.size()) { ASSERTL0(m_f->m_fielddef[0]->m_fields.size() == m_f->m_exp.size(), "More expansion defined than fields"); for(int n = 0; n < m_f->m_exp.size(); ++n) { cnt = 0; int cnt1 = 0; if(m_config["modalenergy"].m_beenSet) { Array<OneD, const NekDouble> phys = m_f->m_exp[n]->GetPhys(); for(int i = 0; i < nel; ++i) { GenOrthoModes(i,phys+cnt,tmp = pts[coordim + n] + cnt1); cnt1 += ppe[i]; cnt += m_f->m_exp[0]->GetExp(i)->GetTotPoints(); } } else { Array<OneD, const NekDouble> phys = m_f->m_exp[n]->GetPhys(); for(int i = 0; i < nel; ++i) { m_f->m_exp[0]->GetExp(i)->PhysInterpToSimplexEquiSpaced( phys + cnt, tmp = pts[coordim + n] + cnt1); cnt1 += ppe[i]; cnt += m_f->m_exp[0]->GetExp(i)->GetTotPoints(); } } // Set up Variable string. fieldNames.push_back(m_f->m_fielddef[0]->m_fields[n]); } } m_f->m_fieldPts = MemoryManager<LibUtilities::PtsField>::AllocateSharedPtr(coordim, fieldNames, pts); if (shapedim == 2) { m_f->m_fieldPts->SetPtsType(LibUtilities::ePtsTriBlock); } else if (shapedim == 3) { m_f->m_fieldPts->SetPtsType(LibUtilities::ePtsTetBlock); } m_f->m_fieldPts->SetConnectivity(ptsConn); } void ProcessEquiSpacedOutput::GenOrthoModes( int n, const Array<OneD,const NekDouble> &phys, Array<OneD, NekDouble> &coeffs) { LocalRegions::ExpansionSharedPtr e; e = m_f->m_exp[0]->GetExp(n); switch(e->DetShapeType()) { case LibUtilities::eTriangle: { int np0 = e->GetBasis(0)->GetNumPoints(); int np1 = e->GetBasis(1)->GetNumPoints(); int np = max(np0,np1); // to ensure points are correctly projected to np need // to increase the order slightly of coordinates LibUtilities::PointsKey pa(np+1,e->GetPointsType(0)); LibUtilities::PointsKey pb(np,e->GetPointsType(1)); Array<OneD, NekDouble> tophys(np*(np+1)); LibUtilities::BasisKey Ba(LibUtilities::eOrtho_A,np,pa); LibUtilities::BasisKey Bb(LibUtilities::eOrtho_B,np,pb); StdRegions::StdTriExp OrthoExp(Ba,Bb); // interpolate points to new phys points! LibUtilities::Interp2D(e->GetBasis(0)->GetBasisKey(), e->GetBasis(1)->GetBasisKey(), phys,Ba,Bb,tophys); OrthoExp.FwdTrans(tophys,coeffs); break; } case LibUtilities::eQuadrilateral: { int np0 = e->GetBasis(0)->GetNumPoints(); int np1 = e->GetBasis(1)->GetNumPoints(); int np = max(np0,np1); LibUtilities::PointsKey pa(np+1,e->GetPointsType(0)); LibUtilities::PointsKey pb(np+1,e->GetPointsType(1)); Array<OneD, NekDouble> tophys((np+1)*(np+1)); LibUtilities::BasisKey Ba(LibUtilities::eOrtho_A,np,pa); LibUtilities::BasisKey Bb(LibUtilities::eOrtho_A,np,pb); StdRegions::StdQuadExp OrthoExp(Ba,Bb); // interpolate points to new phys points! LibUtilities::Interp2D(e->GetBasis(0)->GetBasisKey(), e->GetBasis(1)->GetBasisKey(), phys,Ba,Bb,tophys); OrthoExp.FwdTrans(phys,coeffs); break; } default: ASSERTL0(false,"Shape needs setting up"); break; } } }
namespace Utilities { ModuleKey ProcessDetectSurf::className = GetModuleFactory().RegisterCreatorFunction( ModuleKey(eProcessModule, "detect"), ProcessDetectSurf::create, "Process elements to detect a surface."); ProcessDetectSurf::ProcessDetectSurf(MeshSharedPtr m) : ProcessModule(m) { m_config["vol"] = ConfigOption(false, "-1", "Tag identifying surface to process."); } ProcessDetectSurf::~ProcessDetectSurf() { } struct EdgeInfo { EdgeInfo() : count(0) {} int count; EdgeSharedPtr edge; unsigned int group; }; void ProcessDetectSurf::Process() { if (m_mesh->m_expDim > 2) { cerr << "Surface detection only implemented for 2D meshes" << endl; return; } int i, j; string surf = m_config["vol"].as<string>(); // Obtain vector of surface IDs from string. vector<unsigned int> surfs; if (surf != "-1") { ParseUtils::GenerateSeqVector(surf.c_str(), surfs); sort(surfs.begin(), surfs.end()); } // If we're running in verbose mode print out a list of surfaces. if (m_mesh->m_verbose) { cout << "ProcessDetectSurf: detecting surfaces"; if (surfs.size() > 0) { cout << " for surface" << (surfs.size() == 1 ? "" : "s") << " " << surf << endl; } } vector<ElementSharedPtr> &el = m_mesh->m_element[m_mesh->m_expDim]; map<int, EdgeInfo> edgeCount; set<int> doneIds; map<int, int> idMap; // Iterate over list of surface elements. for (i = 0; i < el.size(); ++i) { // Work out whether this lies on our surface of interest. if (surfs.size() > 0) { vector<int> inter, tags = el[i]->GetTagList(); sort(tags.begin(), tags.end()); set_intersection(surfs.begin(), surfs.end(), tags .begin(), tags .end(), back_inserter(inter)); // It doesn't continue to next element. if (inter.size() != 1) { continue; } } // List all edges. ElementSharedPtr elmt = el[i]; for (j = 0; j < elmt->GetEdgeCount(); ++j) { EdgeSharedPtr e = elmt->GetEdge(j); int eId = e->m_id; edgeCount[eId].count++; edgeCount[eId].edge = e; } doneIds.insert(elmt->GetId()); ASSERTL0(idMap.count(elmt->GetId()) == 0, "Shouldn't happen"); idMap[elmt->GetId()] = i; } CompositeMap::iterator cIt; unsigned int maxId = 0; for (cIt = m_mesh->m_composite.begin(); cIt != m_mesh->m_composite.end(); ++cIt) { maxId = std::max(cIt->first, maxId); } ++maxId; map<int, EdgeInfo>::iterator eIt; while (doneIds.size() > 0) { ElementSharedPtr start = m_mesh->m_element[m_mesh->m_expDim][idMap[*(doneIds.begin())]]; vector<ElementSharedPtr> block; FindContiguousSurface(start, doneIds, block); ASSERTL0(block.size() > 0, "Contiguous block not found"); // Loop over all edges in block. for (i = 0; i < block.size(); ++i) { // Find edge info. ElementSharedPtr elmt = block[i]; for (j = 0; j < elmt->GetEdgeCount(); ++j) { eIt = edgeCount.find(elmt->GetEdge(j)->m_id); ASSERTL0(eIt != edgeCount.end(), "Couldn't find edge"); eIt->second.group = maxId; } } ++maxId; } for (eIt = edgeCount.begin(); eIt != edgeCount.end(); ++eIt) { if (eIt->second.count > 1) { continue; } unsigned int compId = eIt->second.group; CompositeMap::iterator cIt = m_mesh->m_composite.find(compId); if (cIt == m_mesh->m_composite.end()) { CompositeSharedPtr comp(new Composite()); comp->m_id = compId; comp->m_tag = "E"; cIt = m_mesh->m_composite.insert(std::make_pair(compId, comp)).first; } vector<int> tags(1); tags[0] = compId; vector<NodeSharedPtr> nodeList(2); nodeList[0] = eIt->second.edge->m_n1; nodeList[1] = eIt->second.edge->m_n2; ElmtConfig conf(LibUtilities::eSegment, 1, false, false); ElementSharedPtr elmt = GetElementFactory(). CreateInstance(LibUtilities::eSegment,conf,nodeList,tags); elmt->SetEdgeLink(eIt->second.edge); cIt->second->m_items.push_back(elmt); } } void ProcessDetectSurf::FindContiguousSurface( ElementSharedPtr start, set<int> &doneIds, vector<ElementSharedPtr> &block) { block.push_back(start); doneIds.erase(start->GetId()); vector<EdgeSharedPtr> edges = start->GetEdgeList(); for (int i = 0; i < edges.size(); ++i) { for (int j = 0; j < edges[i]->m_elLink.size(); ++j) { ElementSharedPtr elmt = edges[i]->m_elLink[j].first; if (elmt == start) { continue; } if (doneIds.count(elmt->GetId()) == 0) { continue; } FindContiguousSurface(elmt, doneIds, block); } } } }
namespace Utilities { ModuleKey ProcessAddFld::className = GetModuleFactory().RegisterCreatorFunction( ModuleKey(eProcessModule, "addfld"), ProcessAddFld::create, "rescale input field by a constant factor."); ProcessAddFld::ProcessAddFld(FieldSharedPtr f) : ProcessModule(f) { m_config["scale"] = ConfigOption(false, "1.0", "scale factor"); m_config["fromfld"] = ConfigOption(false, "NotSet", "Fld file form which to interpolate field"); ASSERTL0(m_config["fromfld"].as<string>().compare("NotSet") != 0, "Need to specify fromfld=file.fld "); } ProcessAddFld::~ProcessAddFld() { } void ProcessAddFld::Process(po::variables_map &vm) { if (m_f->m_verbose) { cout << "ProcessAddFld: Adding new fld to input fld" << endl; } ASSERTL0(m_f->m_data.size() != 0,"No input data defined"); string scalestr = m_config["scale"].as<string>(); NekDouble scale = boost::lexical_cast<NekDouble>(scalestr); string fromfld = m_config["fromfld"].as<string>(); FieldSharedPtr fromField = boost::shared_ptr<Field>(new Field()); if(m_f->m_exp.size()) { // Set up ElementGIDs in case of parallel processing Array<OneD,int> ElementGIDs(m_f->m_exp[0]->GetExpSize()); for (int i = 0; i < m_f->m_exp[0]->GetExpSize(); ++i) { ElementGIDs[i] = m_f->m_exp[0]->GetExp(i)->GetGeom()->GetGlobalID(); } m_f->m_fld->Import(fromfld,fromField->m_fielddef, fromField->m_data, LibUtilities::NullFieldMetaDataMap, ElementGIDs); } else { m_f->m_fld->Import(fromfld,fromField->m_fielddef, fromField->m_data, LibUtilities::NullFieldMetaDataMap); } bool samelength = true; if(fromField->m_data.size() != m_f->m_data.size()) { samelength = false; } // scale input field for(int i = 0; i < fromField->m_data.size(); ++i) { int datalen = fromField->m_data[i].size(); Vmath::Smul(datalen, scale, &(fromField->m_data[i][0]), 1, &(fromField->m_data[i][0]), 1); if(samelength) { if(datalen != m_f->m_data[i].size()) { samelength = false; } } } if(samelength == true) { for(int i = 0; i < m_f->m_data.size(); ++i) { int datalen = m_f->m_data[i].size(); Vmath::Vadd(datalen, &(m_f->m_data[i][0]), 1, &(fromField->m_data[i][0]), 1, &(m_f->m_data[i][0]), 1); } } else { ASSERTL0(m_f->m_exp.size() != 0 , "Input fields have partitions of different length and so xml " "file needs to be specified"); int nfields = m_f->m_fielddef[0]->m_fields.size(); int ncoeffs = m_f->m_exp[0]->GetNcoeffs(); Array<OneD, NekDouble> SaveFld(ncoeffs); for (int j = 0; j < nfields; ++j) { Vmath::Vcopy(ncoeffs,m_f->m_exp[j]->GetCoeffs(),1, SaveFld,1); // load new field for (int i = 0; i < fromField->m_data.size(); ++i) { m_f->m_exp[j]->ExtractDataToCoeffs( fromField->m_fielddef[i], fromField->m_data[i], fromField->m_fielddef[i]->m_fields[j], m_f->m_exp[j]->UpdateCoeffs()); } Vmath::Vadd(ncoeffs, m_f->m_exp[j]->GetCoeffs(), 1, SaveFld, 1, m_f->m_exp[j]->UpdateCoeffs(), 1); } std::vector<LibUtilities::FieldDefinitionsSharedPtr> FieldDef = m_f->m_exp[0]->GetFieldDefinitions(); std::vector<std::vector<NekDouble> > FieldData(FieldDef.size()); for(int i = 0; i < nfields; ++i) { for (int j = 0; j < FieldDef.size(); ++j) { FieldDef[j]->m_fields.push_back(m_f->m_fielddef[0]->m_fields[i]); m_f->m_exp[i]->AppendFieldData(FieldDef[j], FieldData[j]); } } m_f->m_fielddef = FieldDef; m_f->m_data = FieldData; } } }
namespace Utilities { ModuleKey ProcessWSS::className = GetModuleFactory().RegisterCreatorFunction( ModuleKey(eProcessModule, "wss"), ProcessWSS::create, "Computes wall shear stress field."); ProcessWSS::ProcessWSS(FieldSharedPtr f) : ProcessModule(f) { m_config["bnd"] = ConfigOption(false,"All","Boundary to be extracted"); m_config["addnormals"] = ConfigOption(true,"NotSet","Add normals to output"); f->m_writeBndFld = true; f->m_declareExpansionAsContField = true; m_f->m_fldToBnd = false; } ProcessWSS::~ProcessWSS() { } void ProcessWSS::Process(po::variables_map &vm) { if (m_f->m_verbose) { cout << "ProcessWSS: Calculating wall shear stress..." << endl; } m_f->m_addNormals = m_config["addnormals"].m_beenSet; // Set up Field options to output boundary fld string bvalues = m_config["bnd"].as<string>(); if(bvalues.compare("All") == 0) { Array<OneD, const MultiRegions::ExpListSharedPtr> BndExp = m_f->m_exp[0]->GetBndCondExpansions(); for(int i = 0; i < BndExp.num_elements(); ++i) { m_f->m_bndRegionsToWrite.push_back(i); } } else { ASSERTL0(ParseUtils::GenerateOrderedVector(bvalues.c_str(), m_f->m_bndRegionsToWrite),"Failed to interpret range string"); } NekDouble m_kinvis; m_kinvis = m_f->m_session->GetParameter("Kinvis"); int i, j; int spacedim = m_f->m_graph->GetSpaceDimension(); if ((m_f->m_fielddef[0]->m_numHomogeneousDir) == 1 || (m_f->m_fielddef[0]->m_numHomogeneousDir) == 2) { spacedim = 3; } int nfields = m_f->m_fielddef[0]->m_fields.size(); ASSERTL0(nfields == spacedim +1,"Implicit assumption that input is in incompressible format of (u,v,p) or (u,v,w,p)"); nfields = nfields - 1; if (spacedim == 1) { ASSERTL0(false, "Error: wss for a 1D problem cannot " "be computed"); } int newfields = (spacedim == 2)? 3:4; int nshear = (spacedim == 2)? 3:4; int nstress = (spacedim == 2)? 3:6; int ngrad = nfields*nfields; int n, cnt, elmtid, nq, offset, boundary, nfq; int npoints = m_f->m_exp[0]->GetNpoints(); Array<OneD, Array<OneD, NekDouble> > velocity(nfields), grad(ngrad), fgrad(ngrad); Array<OneD, Array<OneD, NekDouble> > stress(nstress), fstress(nstress); Array<OneD, Array<OneD, NekDouble> > outfield(newfields), fshear(nshear); StdRegions::StdExpansionSharedPtr elmt; StdRegions::StdExpansion2DSharedPtr bc; Array<OneD, int> BoundarytoElmtID, BoundarytoTraceID; Array<OneD, Array<OneD, MultiRegions::ExpListSharedPtr> > BndExp(newfields); m_f->m_exp.resize(newfields); string var = "u"; for(i = nfields+1; i < newfields; ++i) { m_f->m_exp[i] = m_f->AppendExpList(m_f->m_fielddef[0]->m_numHomogeneousDir, var); } m_f->m_fielddef[0]->m_fields.resize(newfields); if(spacedim == 2) { m_f->m_fielddef[0]->m_fields[0] = "Shear_x"; m_f->m_fielddef[0]->m_fields[1] = "Shear_y"; m_f->m_fielddef[0]->m_fields[2] = "Shear_mag"; } else { m_f->m_fielddef[0]->m_fields[0] = "Shear_x"; m_f->m_fielddef[0]->m_fields[1] = "Shear_y"; m_f->m_fielddef[0]->m_fields[2] = "Shear_z"; m_f->m_fielddef[0]->m_fields[3] = "Shear_mag"; } for (i = 0; i < newfields; ++i) { outfield[i] = Array<OneD, NekDouble>(npoints); } for (i = 0; i < nfields; ++i) { velocity[i] = Array<OneD, NekDouble>(npoints); } m_f->m_exp[0]->GetBoundaryToElmtMap(BoundarytoElmtID, BoundarytoTraceID); //get boundary expansions for each field for(int j = 0; j < newfields; ++j) { BndExp[j] = m_f->m_exp[j]->GetBndCondExpansions(); } // loop over the types of boundary conditions for(cnt = n = 0; n < BndExp[0].num_elements(); ++n) { bool doneBnd = false; // identify if boundary has been defined for(int b = 0; b < m_f->m_bndRegionsToWrite.size(); ++b) { if(n == m_f->m_bndRegionsToWrite[b]) { doneBnd = true; for(int i = 0; i < BndExp[0][n]->GetExpSize(); ++i, cnt++) { // find element and face of this expansion. elmtid = BoundarytoElmtID[cnt]; elmt = m_f->m_exp[0]->GetExp(elmtid); nq = elmt->GetTotPoints(); offset = m_f->m_exp[0]->GetPhys_Offset(elmtid); // Initialise local arrays for the velocity gradients, and stress components // size of total number of quadrature points for each element (hence local). for(int j = 0; j < ngrad; ++j) { grad[j] = Array<OneD, NekDouble>(nq); } for(int j = 0; j < nstress; ++j) { stress[j] = Array<OneD, NekDouble>(nq); } if(nfields == 2) { ASSERTL0(false, "Error: not implemented in 2D."); } else { // Get face 2D expansion from element expansion bc = boost::dynamic_pointer_cast<StdRegions::StdExpansion2D> (BndExp[0][n]->GetExp(i)); nfq = bc->GetTotPoints(); //identify boundary of element looking at. boundary = BoundarytoTraceID[cnt]; //Get face normals const SpatialDomains::GeomFactorsSharedPtr m_metricinfo = bc->GetMetricInfo(); const Array<OneD, const Array<OneD, NekDouble> > normals = elmt->GetFaceNormal(boundary); // initialise arrays for(int j = 0; j < nstress; ++j) { fstress[j] = Array<OneD, NekDouble>(nfq); } for(int j = 0; j < nfields*nfields; ++j) { fgrad[j] = Array<OneD, NekDouble>(nfq); } for(int j = 0; j < nshear; ++j) { fshear[j] = Array<OneD, NekDouble>(nfq); } //Extract Velocities for(int j = 0; j < nfields; ++j) { velocity[j] = m_f->m_exp[j]->GetPhys() + offset; } //Compute gradients (velocity correction scheme method) elmt->PhysDeriv(velocity[0],grad[0],grad[1],grad[2]); elmt->PhysDeriv(velocity[1],grad[3],grad[4],grad[5]); elmt->PhysDeriv(velocity[2],grad[6],grad[7],grad[8]); //Compute stress component terms // t_xx = 2.mu.Ux Vmath::Smul (nq,(2*m_kinvis),grad[0],1,stress[0],1); // tyy = 2.mu.Vy Vmath::Smul (nq,(2*m_kinvis),grad[4],1,stress[1],1); // tzz = 2.mu.Wz Vmath::Smul (nq,(2*m_kinvis),grad[8],1,stress[2],1); // txy = mu.(Uy+Vx) Vmath::Vadd (nq,grad[1],1,grad[3],1,stress[3],1); Vmath::Smul (nq,m_kinvis,stress[3],1,stress[3],1); // txz = mu.(Uz+Wx) Vmath::Vadd (nq,grad[2],1,grad[6],1,stress[4],1); Vmath::Smul (nq,m_kinvis,stress[4],1,stress[4],1); // tyz = mu.(Vz+Wy) Vmath::Vadd (nq,grad[5],1,grad[7],1,stress[5],1); Vmath::Smul (nq,m_kinvis,stress[5],1,stress[5],1); // Get face stress values. for(j = 0; j < nstress; ++j) { elmt->GetFacePhysVals(boundary,bc,stress[j],fstress[j]); } //calcuate wss, and update velocity coeffs in the elemental boundary expansion for (j = 0; j< newfields; j++) { outfield[j] = BndExp[j][n]->UpdateCoeffs() + BndExp[j][n]->GetCoeff_Offset(i); } //surface curved if (m_metricinfo->GetGtype() == SpatialDomains::eDeformed) { // Sx Vmath::Vvtvvtp(nfq,normals[0],1,fstress[0],1, normals[1],1,fstress[3],1,fshear[0],1); Vmath::Vvtvp (nfq,normals[2],1,fstress[4],1,fshear[0],1,fshear[0],1); // Sy Vmath::Vvtvvtp(nfq,normals[0],1,fstress[3],1, normals[1],1,fstress[1],1,fshear[1],1); Vmath::Vvtvp (nfq,normals[2],1,fstress[5],1,fshear[1],1,fshear[1],1); // Sz Vmath::Vvtvvtp(nfq,normals[0],1,fstress[4],1, normals[1],1,fstress[5],1,fshear[2],1); Vmath::Vvtvp (nfq,normals[2],1,fstress[2],1,fshear[2],1,fshear[2],1); } else { // Sx Vmath::Svtsvtp(nfq,normals[0][0],fstress[0],1, normals[1][0],fstress[3],1,fshear[0],1); Vmath::Svtvp(nfq,normals[2][0],fstress[4],1,fshear[0],1,fshear[0],1); // Sy Vmath::Svtsvtp(nfq,normals[0][0],fstress[3],1, normals[1][0],fstress[1],1,fshear[1],1); Vmath::Svtvp(nfq,normals[2][0],fstress[5],1,fshear[1],1,fshear[1],1); // Sz Vmath::Svtsvtp(nfq,normals[0][0],fstress[4],1, normals[1][0],fstress[5],1,fshear[2],1); Vmath::Svtvp(nfq,normals[2][0],fstress[2],1,fshear[2],1,fshear[2],1); } // T = T - (T.n)n if (m_metricinfo->GetGtype() == SpatialDomains::eDeformed) { Vmath::Vvtvvtp(nfq,normals[0],1,fshear[0],1, normals[1],1, fshear[1],1,fshear[3],1); Vmath::Vvtvp (nfq,normals[2],1, fshear[2],1,fshear[3],1,fshear[3],1); Vmath::Smul(nfq, -1.0, fshear[3], 1, fshear[3], 1); for (j = 0; j < nfields; j++) { Vmath::Vvtvp(nfq,normals[j], 1, fshear[3], 1, fshear[j], 1, fshear[j], 1); bc->FwdTrans(fshear[j], outfield[j]); } } else { Vmath::Svtsvtp(nfq,normals[0][0],fshear[0],1, normals[1][0],fshear[1],1,fshear[3],1); Vmath::Svtvp(nfq,normals[2][0],fshear[2],1,fshear[3],1,fshear[3],1); Vmath::Smul(nfq, -1.0, fshear[3], 1,fshear[3], 1); for (j = 0; j < nfields; j++) { Vmath::Svtvp(nfq,normals[j][0],fshear[3],1,fshear[j],1,fshear[j],1); bc->FwdTrans(fshear[j], outfield[j]); } } // Tw Vmath::Vvtvvtp(nfq, fshear[0], 1, fshear[0], 1, fshear[1], 1, fshear[1], 1, fshear[3], 1); Vmath::Vvtvp(nfq, fshear[2], 1, fshear[2], 1, fshear[3], 1, fshear[3], 1); Vmath::Vsqrt(nfq, fshear[3], 1, fshear[3], 1); bc->FwdTrans(fshear[3], outfield[3]); } } } } if(doneBnd == false) { cnt += BndExp[0][n]->GetExpSize(); } } for(int j = 0; j < newfields; ++j) { for(int b = 0; b < m_f->m_bndRegionsToWrite.size(); ++b) { m_f->m_exp[j]->UpdateBndCondExpansion(m_f->m_bndRegionsToWrite[b]) = BndExp[j][m_f->m_bndRegionsToWrite[b]]; } } } }
namespace Utilities { ModuleKey InputVtk::className = GetModuleFactory().RegisterCreatorFunction( ModuleKey(eInputModule, "vtk"), InputVtk::create, "Reads VTK format."); InputVtk::InputVtk(MeshSharedPtr m) : InputModule(m) { } InputVtk::~InputVtk() { } /** * Gmsh file contains a list of nodes and their coordinates, along with * a list of elements and those nodes which define them. We read in and * store the list of nodes in #m_node and store the list of elements in * #m_element. Each new element is supplied with a list of entries from * #m_node which defines the element. Finally some mesh statistics are * printed. * * @param pFilename Filename of Gmsh file to read. */ void InputVtk::Process() { if (m_mesh->m_verbose) { cout << "InputVtk: Start reading file..." << endl; } vtkPolyDataReader *vtkMeshReader = vtkPolyDataReader::New(); vtkMeshReader->SetFileName(m_config["infile"].as<string>().c_str()); vtkMeshReader->Update(); vtkPolyData *vtkMesh = vtkMeshReader->GetOutput(); vtkPoints *vtkPoints = vtkMesh->GetPoints(); const int numCellTypes = 3; vtkCellArray* vtkCells[numCellTypes]; LibUtilities::ShapeType vtkCellTypes[numCellTypes]; int vtkNumPoints[numCellTypes]; vtkCells[0] = vtkMesh->GetPolys(); vtkCells[1] = vtkMesh->GetStrips(); vtkCells[2] = vtkMesh->GetLines(); vtkCellTypes[0] = LibUtilities::eTriangle; vtkCellTypes[1] = LibUtilities::eTriangle; vtkCellTypes[2] = LibUtilities::eSegment; vtkNumPoints[0] = 3; vtkNumPoints[1] = 3; vtkNumPoints[2] = 2; vtkIdType npts; vtkIdType *pts = 0; double p[3]; for (int i = 0; i < vtkPoints->GetNumberOfPoints(); ++i) { vtkPoints->GetPoint(i, p); if ((p[0] * p[0]) > 0.000001 && m_mesh->m_spaceDim < 1) { m_mesh->m_spaceDim = 1; } if ((p[1] * p[1]) > 0.000001 && m_mesh->m_spaceDim < 2) { m_mesh->m_spaceDim = 2; } if ((p[2] * p[2]) > 0.000001 && m_mesh->m_spaceDim < 3) { m_mesh->m_spaceDim = 3; } m_mesh->m_node.push_back(boost::shared_ptr<Node>(new Node(i, p[0], p[1], p[2]))); } for (int c = 0; c < numCellTypes; ++c) { vtkCells[c]->InitTraversal(); for (int i = 0; vtkCells[c]->GetNextCell(npts, pts); ++i) { for (int j = 0; j < npts - vtkNumPoints[c] + 1; ++j) { // Create element tags vector<int> tags; tags.push_back(0); // composite tags.push_back(vtkCellTypes[c]); // element type // Read element node list vector<NodeSharedPtr> nodeList; for (int k = j; k < j + vtkNumPoints[c]; ++k) { nodeList.push_back(m_mesh->m_node[pts[k]]); } // Create element ElmtConfig conf(vtkCellTypes[c],1,false,false); ElementSharedPtr E = GetElementFactory(). CreateInstance(vtkCellTypes[c], conf,nodeList,tags); // Determine mesh expansion dimension if (E->GetDim() > m_mesh->m_expDim) { m_mesh->m_expDim = E->GetDim(); } m_mesh->m_element[E->GetDim()].push_back(E); } } } ProcessVertices(); ProcessEdges(); ProcessFaces(); ProcessElements(); ProcessComposites(); } }