Teuchos::RCP<const Teuchos::ParameterList> IfpackPreconditionerFactory::getValidParameters() const { using Teuchos::rcp; using Teuchos::rcp_implicit_cast; typedef Teuchos::ParameterEntryValidator PEV; static Teuchos::RCP<Teuchos::ParameterList> validParamList; if(validParamList.get()==NULL) { validParamList = Teuchos::rcp(new Teuchos::ParameterList(Ifpack_name)); { // Create the validator for the preconditioner type! Teuchos::Array<std::string> precTypeNames; precTypeNames.insert( precTypeNames.begin(), &Ifpack::precTypeNames[0], &Ifpack::precTypeNames[0] + Ifpack::numPrecTypes ); Teuchos::Array<Ifpack::EPrecType> precTypeValues; precTypeValues.insert( precTypeValues.begin(), &Ifpack::precTypeValues[0], &Ifpack::precTypeValues[0] + Ifpack::numPrecTypes ); precTypeValidator = rcp( new Teuchos::StringToIntegralParameterEntryValidator<Ifpack::EPrecType>( precTypeNames,precTypeValues,PrecType_name ) ); } validParamList->set( PrecType_name, PrecTypeName_default, "Type of Ifpack preconditioner to use.", rcp_implicit_cast<const PEV>(precTypeValidator) ); validParamList->set( Overlap_name, Overlap_default, "Number of rows/columns overlapped between subdomains in different" "\nprocesses in the additive Schwarz-type domain-decomposition preconditioners." ); validParamList->sublist( IfpackSettings_name, false, "Preconditioner settings that are passed onto the Ifpack preconditioners themselves." ).setParameters(Ifpack_GetValidParameters()); // Note that in the above setParameterList(...) function that we actually // validate down into the first level of this sublist. Really the // Ifpack_Preconditioner objects themselves should do validation but we do // it ourselves taking the return from the Ifpack_GetValidParameters() // function as gospel! Teuchos::setupVerboseObjectSublist(&*validParamList); } return validParamList; }
Teuchos::RCP<Epetra_Map> Albany::SolutionResponseFunction:: buildCulledMap(const Epetra_Map& x_map, const Teuchos::Array<int>& keepDOF) const { int numKeepDOF = std::accumulate(keepDOF.begin(), keepDOF.end(), 0); int Neqns = keepDOF.size(); int N = x_map.NumMyElements(); // x_map is map for solution vector TEUCHOS_ASSERT( !(N % Neqns) ); // Assume that all the equations for // a given node are on the assigned // processor. I.e. need to ensure // that N is exactly Neqns-divisible int nnodes = N / Neqns; // number of fem nodes int N_new = nnodes * numKeepDOF; // length of local x_new int *gids = x_map.MyGlobalElements(); // Fill local x_map into gids array Teuchos::Array<int> gids_new(N_new); int idx = 0; for ( int inode = 0; inode < N/Neqns ; ++inode) // For every node for ( int ieqn = 0; ieqn < Neqns; ++ieqn ) // Check every dof on the node if ( keepDOF[ieqn] == 1 ) // then want to keep this dof gids_new[idx++] = gids[(inode*Neqns)+ieqn]; // end cull Teuchos::RCP<Epetra_Map> x_new_map = Teuchos::rcp( new Epetra_Map( -1, N_new, &gids_new[0], 0, x_map.Comm() ) ); return x_new_map; }
Teuchos::Array<EpetraGlobalIndex> getMyLIDs( const Epetra_BlockMap &map, const Teuchos::ArrayView<const EpetraGlobalIndex> &selectedGIDs) { Teuchos::Array<EpetraGlobalIndex> sortedMyGIDs(map.MyGlobalElements(), map.MyGlobalElements() + map.NumMyElements()); std::sort(sortedMyGIDs.begin(), sortedMyGIDs.end()); Teuchos::Array<EpetraGlobalIndex> sortedSelectedGIDs(selectedGIDs); std::sort(sortedSelectedGIDs.begin(), sortedSelectedGIDs.end()); Teuchos::Array<EpetraGlobalIndex> mySelectedGIDs; std::set_intersection(sortedMyGIDs.begin(), sortedMyGIDs.end(), sortedSelectedGIDs.begin(), sortedSelectedGIDs.end(), std::back_inserter(mySelectedGIDs)); Teuchos::Array<EpetraGlobalIndex> result; result.reserve(mySelectedGIDs.size()); std::transform( mySelectedGIDs.begin(), mySelectedGIDs.end(), std::back_inserter(result), std::bind1st(std::mem_fun_ref(static_cast<int(Epetra_BlockMap::*)(EpetraGlobalIndex) const>(&Epetra_BlockMap::LID)), map)); return result; }
Teuchos::Array<GO> Albany::NodeGIDsSolutionCullingStrategy:: selectedGIDsT(Teuchos::RCP<const Tpetra_Map> sourceMapT) const { Teuchos::Array<GO> result; { Teuchos::Array<GO> mySelectedGIDs; // Subract 1 to convert exodus GIDs to our GIDs for (int i=0; i<nodeGIDs_.size(); i++) if (sourceMapT->isNodeGlobalElement(nodeGIDs_[i] -1) ) mySelectedGIDs.push_back(nodeGIDs_[i] - 1); Teuchos::RCP<const Teuchos::Comm<int> >commT = sourceMapT->getComm(); { GO selectedGIDCount; { GO mySelectedGIDCount = mySelectedGIDs.size(); Teuchos::reduceAll<LO, GO>(*commT, Teuchos::REDUCE_SUM, 1, &mySelectedGIDCount, &selectedGIDCount); } result.resize(selectedGIDCount); } const int ierr = Tpetra::GatherAllV( commT, mySelectedGIDs.getRawPtr(), mySelectedGIDs.size(), result.getRawPtr(), result.size()); TEUCHOS_ASSERT(ierr == 0); } std::sort(result.begin(), result.end()); return result; }
Teuchos::Array<int> Albany::NodeGIDsSolutionCullingStrategy:: selectedGIDs(const Epetra_BlockMap &sourceMap) const { Teuchos::Array<int> result; { Teuchos::Array<int> mySelectedGIDs; // Subract 1 to convert exodus GIDs to our GIDs for (int i=0; i<nodeGIDs_.size(); i++) if (sourceMap.MyGID(nodeGIDs_[i] -1) ) mySelectedGIDs.push_back(nodeGIDs_[i] - 1); const Epetra_Comm &comm = sourceMap.Comm(); { int selectedGIDCount; { int mySelectedGIDCount = mySelectedGIDs.size(); comm.SumAll(&mySelectedGIDCount, &selectedGIDCount, 1); } result.resize(selectedGIDCount); } const int ierr = Epetra::GatherAllV( comm, mySelectedGIDs.getRawPtr(), mySelectedGIDs.size(), result.getRawPtr(), result.size()); TEUCHOS_ASSERT(ierr == 0); } std::sort(result.begin(), result.end()); return result; }
Adapter * Adapter::initialize(const Teuchos::RCP<Teuchos::ParameterList>& catalystParams) { // Validate parameters against list for this specific class catalystParams->validateParameters(*getValidAdapterParameters(),0); if (Adapter::instance) delete Adapter::instance; Adapter::instance = new Adapter(); // Register our Grid class with Catalyst so that it can be used in a pipeline. if (vtkClientServerInterpreterInitializer *intInit = vtkClientServerInterpreterInitializer::GetInitializer()) { if (vtkClientServerInterpreter *interp = intInit->GetGlobalInterpreter()) { interp->AddNewInstanceFunction("Grid", Private::MakeGrid); } } // Load pipeline file Teuchos::Array<std::string> files = catalystParams->get<Teuchos::Array<std::string> >("Pipeline Files"); typedef Teuchos::Array<std::string>::const_iterator FileIterT; for (FileIterT it = files.begin(), itEnd = files.end(); it != itEnd; ++it) Adapter::instance->addPythonScriptPipeline(*it); return Adapter::instance; }
Teuchos::RCP<const Tpetra_Map> Albany::SolutionResponseFunction:: buildCulledMapT(const Tpetra_Map& x_mapT, const Teuchos::Array<int>& keepDOF) const { int numKeepDOF = std::accumulate(keepDOF.begin(), keepDOF.end(), 0); int Neqns = keepDOF.size(); int N = x_mapT.getNodeNumElements(); // x_mapT is map for solution vector TEUCHOS_ASSERT( !(N % Neqns) ); // Assume that all the equations for // a given node are on the assigned // processor. I.e. need to ensure // that N is exactly Neqns-divisible int nnodes = N / Neqns; // number of fem nodes int N_new = nnodes * numKeepDOF; // length of local x_new Teuchos::ArrayView<const GO> gidsT = x_mapT.getNodeElementList(); Teuchos::Array<GO> gids_new(N_new); int idx = 0; for ( int inode = 0; inode < N/Neqns ; ++inode) // For every node for ( int ieqn = 0; ieqn < Neqns; ++ieqn ) // Check every dof on the node if ( keepDOF[ieqn] == 1 ) // then want to keep this dof gids_new[idx++] = gidsT[(inode*Neqns)+ieqn]; // end cull Teuchos::RCP<const Tpetra_Map> x_new_mapT = Tpetra::createNonContigMapWithNode<LO, GO, KokkosNode> (gids_new, x_mapT.getComm(), x_mapT.getNode()); return x_new_mapT; }
/*! * \brief Find the set of entities a point neighbors. */ void CoarseLocalSearch::search( const Teuchos::ArrayView<const double>& point, const Teuchos::ParameterList& parameters, Teuchos::Array<Entity>& neighbors ) const { // Find the leaf of nearest neighbors. int num_neighbors = 100; if ( parameters.isParameter("Coarse Local Search kNN") ) { num_neighbors = parameters.get<int>("Coarse Local Search kNN"); } num_neighbors = std::min( num_neighbors, Teuchos::as<int>(d_entity_map.size()) ); Teuchos::Array<unsigned> local_neighbors = d_tree->nnSearch( point, num_neighbors ); // Extract the neighbors. neighbors.resize( local_neighbors.size() ); Teuchos::Array<unsigned>::const_iterator local_it; Teuchos::Array<Entity>::iterator entity_it; for ( local_it = local_neighbors.begin(), entity_it = neighbors.begin(); local_it != local_neighbors.end(); ++local_it, ++entity_it ) { DTK_CHECK( d_entity_map.count(*local_it) ); *entity_it = d_entity_map.find(*local_it)->second; } }
void epetraFromThyra( const Teuchos::RCP<const Epetra_Comm> &comm, const Teuchos::Array<Teuchos::RCP<const Thyra::VectorBase<double> > > &thyraResponses, const Teuchos::Array<Teuchos::Array<Teuchos::RCP<const Thyra::MultiVectorBase<double> > > > &thyraSensitivities, Teuchos::Array<Teuchos::RCP<const Epetra_Vector> > &responses, Teuchos::Array<Teuchos::Array<Teuchos::RCP<const Epetra_MultiVector> > > &sensitivities) { responses.clear(); responses.reserve(thyraResponses.size()); typedef Teuchos::Array<Teuchos::RCP<const Thyra::VectorBase<double> > > ThyraResponseArray; for (ThyraResponseArray::const_iterator it_begin = thyraResponses.begin(), it_end = thyraResponses.end(), it = it_begin; it != it_end; ++it) { responses.push_back(epetraVectorFromThyra(comm, *it)); } sensitivities.clear(); sensitivities.reserve(thyraSensitivities.size()); typedef Teuchos::Array<Teuchos::Array<Teuchos::RCP<const Thyra::MultiVectorBase<double> > > > ThyraSensitivityArray; for (ThyraSensitivityArray::const_iterator it_begin = thyraSensitivities.begin(), it_end = thyraSensitivities.end(), it = it_begin; it != it_end; ++it) { ThyraSensitivityArray::const_reference sens_thyra = *it; Teuchos::Array<Teuchos::RCP<const Epetra_MultiVector> > sens; sens.reserve(sens_thyra.size()); for (ThyraSensitivityArray::value_type::const_iterator jt = sens_thyra.begin(), jt_end = sens_thyra.end(); jt != jt_end; ++jt) { sens.push_back(epetraMultiVectorFromThyra(comm, *jt)); } sensitivities.push_back(sens); } }
BoundingBox GeometryManager<Geometry,GlobalOrdinal>::localBoundingBox() const { double global_x_min = Teuchos::ScalarTraits<double>::rmax(); double global_y_min = Teuchos::ScalarTraits<double>::rmax(); double global_z_min = Teuchos::ScalarTraits<double>::rmax(); double global_x_max = -Teuchos::ScalarTraits<double>::rmax(); double global_y_max = -Teuchos::ScalarTraits<double>::rmax(); double global_z_max = -Teuchos::ScalarTraits<double>::rmax(); // Get the local bounding boxes compute the local bounding box. BoundingBox local_box; Teuchos::Tuple<double,6> box_bounds; Teuchos::Array<BoundingBox> boxes = boundingBoxes(); Teuchos::Array<BoundingBox>::const_iterator box_iterator; DTK_CHECK( !boxes.empty() ); for ( box_iterator = boxes.begin(); box_iterator != boxes.end(); ++box_iterator ) { box_bounds = box_iterator->getBounds(); if ( box_bounds[0] < global_x_min ) { global_x_min = box_bounds[0]; } if ( box_bounds[1] < global_y_min ) { global_y_min = box_bounds[1]; } if ( box_bounds[2] < global_z_min ) { global_z_min = box_bounds[2]; } if ( box_bounds[3] > global_x_max ) { global_x_max = box_bounds[3]; } if ( box_bounds[4] > global_y_max ) { global_y_max = box_bounds[4]; } if ( box_bounds[5] > global_z_max ) { global_z_max = box_bounds[5]; } } return BoundingBox( global_x_min, global_y_min, global_z_min, global_x_max, global_y_max, global_z_max ); }
size_type computeSize(const Teuchos::Array< DIM_TYPE > & dimensions) { // In the MDArray<T>(const MDArrayView<T> &) constructor, I try to // pass the MDArrayView dimensions to computeSize(), but they come // in as ArrayView<const T> (for reasons I can't determine) and // cause all sorts of const-correctness problems. So I copy them // into a new Array<T> and pass its view to the main computeSize() // function. Fortunately, the array of dimensions is small. Teuchos::Array< DIM_TYPE > nonConstDims(0); nonConstDims.insert(nonConstDims.begin(), dimensions.begin(), dimensions.end()); return computeSize(nonConstDims()); }
void tpetraFromThyra( const Teuchos::Array<Teuchos::RCP<const Thyra::VectorBase<ST> > > &thyraResponses, const Teuchos::Array<Teuchos::Array<Teuchos::RCP<const Thyra::MultiVectorBase<ST> > > > &thyraSensitivities, Teuchos::Array<Teuchos::RCP<const Tpetra_Vector> > &responses, Teuchos::Array<Teuchos::Array<Teuchos::RCP<const Tpetra_MultiVector> > > &sensitivities) { responses.clear(); responses.reserve(thyraResponses.size()); typedef Teuchos::Array<Teuchos::RCP<const Thyra::VectorBase<ST> > > ThyraResponseArray; for (ThyraResponseArray::const_iterator it_begin = thyraResponses.begin(), it_end = thyraResponses.end(), it = it_begin; it != it_end; ++it) { responses.push_back(Teuchos::nonnull(*it) ? ConverterT::getConstTpetraVector(*it) : Teuchos::null); } sensitivities.clear(); sensitivities.reserve(thyraSensitivities.size()); typedef Teuchos::Array<Teuchos::Array<Teuchos::RCP<const Thyra::MultiVectorBase<ST> > > > ThyraSensitivityArray; for (ThyraSensitivityArray::const_iterator it_begin = thyraSensitivities.begin(), it_end = thyraSensitivities.end(), it = it_begin; it != it_end; ++it) { ThyraSensitivityArray::const_reference sens_thyra = *it; Teuchos::Array<Teuchos::RCP<const Tpetra_MultiVector> > sens; sens.reserve(sens_thyra.size()); for (ThyraSensitivityArray::value_type::const_iterator jt = sens_thyra.begin(), jt_end = sens_thyra.end(); jt != jt_end; ++jt) { sens.push_back(Teuchos::nonnull(*jt) ? ConverterT::getConstTpetraMultiVector(*jt) : Teuchos::null); } sensitivities.push_back(sens); } }
//---------------------------------------------------------------------------// // Given a range entity id, get the ids of the domain entities that it mapped to. void ParallelSearch::getDomainEntitiesFromRange( const EntityId range_id, Teuchos::Array<EntityId>& domain_ids ) const { DTK_REQUIRE( !d_empty_range ); auto range_pair = d_range_to_domain_map.equal_range( range_id ); domain_ids.resize( std::distance(range_pair.first,range_pair.second) ); auto domain_it = domain_ids.begin(); for ( auto range_it = range_pair.first; range_it != range_pair.second; ++range_it, ++domain_it ) { *domain_it = range_it->second; } }
//---------------------------------------------------------------------------// // Given a domain entity id, get the ids of the range entities that mapped to it. void ParallelSearch::getRangeEntitiesFromDomain( const EntityId domain_id, Teuchos::Array<EntityId>& range_ids ) const { DTK_REQUIRE( !d_empty_domain ); auto domain_pair = d_domain_to_range_map.equal_range( domain_id ); range_ids.resize( std::distance(domain_pair.first,domain_pair.second) ); auto range_it = range_ids.begin(); for ( auto domain_it = domain_pair.first; domain_it != domain_pair.second; ++domain_it, ++range_it ) { *range_it = domain_it->second; } }
Teuchos::Array<int> Albany::NodeSetSolutionCullingStrategy:: selectedGIDs(const Epetra_BlockMap &sourceMap) const { Teuchos::Array<int> result; { Teuchos::Array<int> mySelectedGIDs; { const NodeSetList &nodeSets = disc_->getNodeSets(); const NodeSetList::const_iterator it = nodeSets.find(nodeSetLabel_); if (it != nodeSets.end()) { typedef NodeSetList::mapped_type NodeSetEntryList; const NodeSetEntryList &sampleNodeEntries = it->second; for (NodeSetEntryList::const_iterator jt = sampleNodeEntries.begin(); jt != sampleNodeEntries.end(); ++jt) { typedef NodeSetEntryList::value_type NodeEntryList; const NodeEntryList &sampleEntries = *jt; for (NodeEntryList::const_iterator kt = sampleEntries.begin(); kt != sampleEntries.end(); ++kt) { mySelectedGIDs.push_back(sourceMap.GID(*kt)); } } } } const Epetra_Comm &comm = sourceMap.Comm(); { int selectedGIDCount; { int mySelectedGIDCount = mySelectedGIDs.size(); comm.SumAll(&mySelectedGIDCount, &selectedGIDCount, 1); } result.resize(selectedGIDCount); } const int ierr = Epetra::GatherAllV( comm, mySelectedGIDs.getRawPtr(), mySelectedGIDs.size(), result.getRawPtr(), result.size()); TEUCHOS_ASSERT(ierr == 0); } std::sort(result.begin(), result.end()); return result; }
Teuchos::Array<GO> Albany::NodeSetSolutionCullingStrategy:: selectedGIDsT(Teuchos::RCP<const Tpetra_Map> sourceMapT) const { Teuchos::Array<GO> result; { Teuchos::Array<GO> mySelectedGIDs; { const NodeSetList &nodeSets = disc_->getNodeSets(); const NodeSetList::const_iterator it = nodeSets.find(nodeSetLabel_); if (it != nodeSets.end()) { typedef NodeSetList::mapped_type NodeSetEntryList; const NodeSetEntryList &sampleNodeEntries = it->second; for (NodeSetEntryList::const_iterator jt = sampleNodeEntries.begin(); jt != sampleNodeEntries.end(); ++jt) { typedef NodeSetEntryList::value_type NodeEntryList; const NodeEntryList &sampleEntries = *jt; for (NodeEntryList::const_iterator kt = sampleEntries.begin(); kt != sampleEntries.end(); ++kt) { mySelectedGIDs.push_back(sourceMapT->getGlobalElement(*kt)); } } } } Teuchos::RCP<const Teuchos::Comm<int> >commT = sourceMapT->getComm(); { GO selectedGIDCount; { GO mySelectedGIDCount = mySelectedGIDs.size(); Teuchos::reduceAll<LO, GO>(*commT, Teuchos::REDUCE_SUM, 1, &mySelectedGIDCount, &selectedGIDCount); } result.resize(selectedGIDCount); } const int ierr = Tpetra::GatherAllV( commT, mySelectedGIDs.getRawPtr(), mySelectedGIDs.size(), result.getRawPtr(), result.size()); TEUCHOS_ASSERT(ierr == 0); } std::sort(result.begin(), result.end()); return result; }
bool IsInRangeList(const Integral val, const Teuchos::Array<Integral> &valList, bool sorted=true) { if (allValuesAreInRangeList(valList)) return true; else if (noValuesAreInRangeList(valList)) return false; if (sorted){ typename Teuchos::Array<Integral>::const_iterator flag = valList.end(); --flag; if (std::binary_search(valList.begin(), flag, val)) return true; else return false; } else{ for (typename Teuchos::Array<Integral>::size_type i=0; i < valList.size()-1; i++){ if (valList[i] == val) return true; } return false; } }
int order( const RCP<GraphModel<Adapter> > &model, const RCP<OrderingSolution<typename Adapter::gid_t, typename Adapter::lno_t> > &solution, const RCP<Teuchos::ParameterList> &pl, const RCP<Teuchos::Comm<int> > &comm ) { int ierr= 0; HELLO; // Check size of communicator: serial only. // TODO: Remove this test when RCM works on local graph. if (comm->getSize() > 1){ throw std::runtime_error("RCM currently only works in serial."); } // Get local graph. ArrayView<const gno_t> edgeIds; ArrayView<const lno_t> offsets; ArrayView<StridedData<lno_t, scalar_t> > wgts; // TODO: edgeIds should be of type lno_t for getLocalEdgeList. Needs revisit. //model->getLocalEdgeList(edgeIds, offsets, wgts); // BUGGY! // Use global graph for now. This only works in serial! ArrayView<const int> procIds; size_t numEdges = model->getEdgeList( edgeIds, procIds, offsets, wgts); //cout << "Debug: Local graph from getLocalEdgeList" << endl; //cout << "edgeIds: " << edgeIds << endl; //cout << "offsets: " << offsets << endl; const size_t nVtx = model->getLocalNumVertices(); // RCM constructs invPerm, not perm ArrayRCP<lno_t> invPerm = solution->getPermutationRCP(true); // Check if there are actually edges to reorder. // If there are not, then just use the natural ordering. if (numEdges == 0) { for (size_t i = 0; i < nVtx; ++i) { invPerm[i] = i; } return 0; } // Set the label of each vertex to invalid. Tpetra::global_size_t INVALID = Teuchos::OrdinalTraits<Tpetra::global_size_t>::invalid(); for (size_t i = 0; i < nVtx; ++i) { invPerm[i] = INVALID; } // Loop over all connected components. // Do BFS within each component. lno_t root; std::queue<lno_t> Q; size_t count = 0; // CM label, reversed later size_t next = 0; // next unmarked vertex Teuchos::Array<std::pair<lno_t, size_t> > children; // children and their degrees while (count < nVtx) { // Find suitable root vertex for this component. // First find an unmarked vertex, use to find root in next component. while ((next < nVtx) && (static_cast<Tpetra::global_size_t>(invPerm[next]) != INVALID)) next++; // Select root method. Pseudoperipheral usually gives the best // ordering, but the user may choose a faster method. std::string root_method = pl->get("root_method", "pseudoperipheral"); if (root_method == string("first")) root = next; else if (root_method == string("smallest_degree")) root = findSmallestDegree(next, nVtx, edgeIds, offsets); else if (root_method == string("pseudoperipheral")) root = findPseudoPeripheral(next, nVtx, edgeIds, offsets); else { // This should never happen if pl was validated. } // Label connected component starting at root Q.push(root); //cout << "Debug: invPerm[" << root << "] = " << count << endl; invPerm[root] = count++; while (Q.size()){ // Get a vertex from the queue lno_t v = Q.front(); Q.pop(); //cout << "Debug: v= " << v << ", offsets[v] = " << offsets[v] << endl; // Add unmarked children to list of pairs, to be added to queue. children.resize(0); for (lno_t ptr = offsets[v]; ptr < offsets[v+1]; ++ptr){ lno_t child = edgeIds[ptr]; if (static_cast<Tpetra::global_size_t>(invPerm[child]) == INVALID){ // Not visited yet; add child to list of pairs. std::pair<lno_t,size_t> newchild; newchild.first = child; newchild.second = offsets[child+1] - offsets[child]; children.push_back(newchild); } } // Sort children by increasing degree // TODO: If edge weights, sort children by decreasing weight, SortPairs<lno_t,size_t> zort; zort.sort(children); typename Teuchos::Array<std::pair<lno_t,size_t> >::iterator it = children.begin (); for ( ; it != children.end(); ++it){ // Push children on the queue in sorted order. lno_t child = it->first; invPerm[child] = count++; // Label as we push on Q Q.push(child); //cout << "Debug: invPerm[" << child << "] = " << count << endl; } } } // Reverse labels for RCM bool reverse = true; // TODO: Make parameter if (reverse) { lno_t temp; for (size_t i=0; i < nVtx/2; ++i) { // Swap (invPerm[i], invPerm[nVtx-i]) temp = invPerm[i]; invPerm[i] = invPerm[nVtx-1-i]; invPerm[nVtx-1-i] = temp; } } solution->setHaveInverse(true); return ierr; }
/* * \brief This constructor will pull the mesh data DTK needs out of Moab, * partition it for the example, and build a DataTransferKit::MeshContainer * object from the local data in the partition. You can directly write the * traits interface yourself, but this is probably the easiest way to get * started (although potentially inefficient). */ MoabMesh::MoabMesh( const RCP_Comm& comm, const std::string& filename, const moab::EntityType& block_topology, const int partitioning_type ) : d_comm( comm ) { // Compute the node dimension. int node_dim = 0; if ( block_topology == moab::MBTRI ) { node_dim = 2; } else if ( block_topology == moab::MBQUAD ) { node_dim = 2; } else if ( block_topology == moab::MBTET ) { node_dim = 3; } else if ( block_topology == moab::MBHEX ) { node_dim = 3; } else if ( block_topology == moab::MBPYRAMID ) { node_dim = 3; } else { node_dim = 0; } // Create a moab instance. moab::ErrorCode error; d_moab = Teuchos::rcp( new moab::Core() ); std::cout<<"Filename: "<<filename<<std::endl; // Load the mesh. d_moab->load_mesh( &filename[0] ); moab::EntityHandle root_set = d_moab->get_root_set(); // Extract the elements with this block's topology. std::vector<moab::EntityHandle> global_elements; error = d_moab->get_entities_by_type( root_set, block_topology, global_elements ); assert( error == moab::MB_SUCCESS ); std::cout<<"Global elements: "<<global_elements.size()<<std::endl; // Partition the mesh. int comm_size = d_comm->getSize(); int comm_rank = d_comm->getRank(); // Get the number of nodes in an element. std::vector<moab::EntityHandle> elem_vertices; error = d_moab->get_adjacencies( &global_elements[0], 1, 0, false, elem_vertices ); assert( error == moab::MB_SUCCESS ); int nodes_per_element = elem_vertices.size(); // Get the global element coordinates. std::vector<double> global_coords; error = d_moab->get_vertex_coordinates( global_coords ); assert( error == moab::MB_SUCCESS ); // Get the global max and min values for the coordinates. This problem is // symmetric. double min = *(std::min_element( global_coords.begin(), global_coords.end() ) ); double max = *(std::max_element( global_coords.begin(), global_coords.end() ) ); double width = max - min; Teuchos::Array<moab::EntityHandle> elements; elem_vertices.resize( nodes_per_element ); std::vector<double> elem_coords( 3*nodes_per_element ); std::vector<moab::EntityHandle>::const_iterator global_elem_iterator; for ( global_elem_iterator = global_elements.begin(); global_elem_iterator != global_elements.end(); ++global_elem_iterator ) { // Get the individual element vertices. error = d_moab->get_adjacencies( &*global_elem_iterator, 1, 0, false, elem_vertices ); assert( error == moab::MB_SUCCESS ); // Get the invidivual element coordinates. error = d_moab->get_coords( &elem_vertices[0], elem_vertices.size(), &elem_coords[0] ); assert( error == moab::MB_SUCCESS ); // Partition in x direction. if ( partitioning_type == 0 ) { for ( int i = 0; i < comm_size; ++i ) { if ( elem_coords[0] >= min + width*(comm_rank)/comm_size - 1e-6 && elem_coords[0] <= min + width*(comm_rank+1)/comm_size + 1e-6 ) { elements.push_back( *global_elem_iterator ); } } } // Partition in y direction. else if ( partitioning_type == 1 ) { for ( int i = 0; i < comm_size; ++i ) { if ( elem_coords[1] >= min + width*(comm_rank)/comm_size - 1e-6 && elem_coords[1] <= min + width*(comm_rank+1)/comm_size + 1e-6 ) { elements.push_back( *global_elem_iterator ); } } } else { throw std::logic_error( "Partitioning type not supported." ); } } Teuchos::ArrayRCP<moab::EntityHandle> elements_arcp( elements.size() ); std::copy( elements.begin(), elements.end(), elements_arcp.begin() ); elements.clear(); d_comm->barrier(); // Get the nodes. std::vector<moab::EntityHandle> vertices; error = d_moab->get_connectivity( &elements_arcp[0], elements_arcp.size(), vertices ); assert( error == moab::MB_SUCCESS ); d_vertices = Teuchos::ArrayRCP<moab::EntityHandle>( vertices.size() ); std::copy( vertices.begin(), vertices.end(), d_vertices.begin() ); vertices.clear(); // Get the node coordinates. Teuchos::ArrayRCP<double> coords( node_dim * d_vertices.size() ); std::vector<double> interleaved_coords( 3*d_vertices.size() ); error = d_moab->get_coords( &d_vertices[0], d_vertices.size(), &interleaved_coords[0] ); assert( error == moab::MB_SUCCESS ); for ( int n = 0; n < (int) d_vertices.size(); ++n ) { for ( int d = 0; d < (int) node_dim; ++d ) { coords[ d*d_vertices.size() + n ] = interleaved_coords[ n*3 + d ]; } } interleaved_coords.clear(); // Get the connectivity. int connectivity_size = elements_arcp.size() * nodes_per_element; Teuchos::ArrayRCP<moab::EntityHandle> connectivity( connectivity_size ); std::vector<moab::EntityHandle> elem_conn; for ( int i = 0; i < (int) elements_arcp.size(); ++i ) { error = d_moab->get_connectivity( &elements_arcp[i], 1, elem_conn ); assert( error == moab::MB_SUCCESS ); assert( elem_conn.size() == Teuchos::as<std::vector<moab::EntityHandle>::size_type>(nodes_per_element) ); for ( int n = 0; n < (int) elem_conn.size(); ++n ) { connectivity[ n*elements_arcp.size() + i ] = elem_conn[n]; } } // Get the permutation vector. Teuchos::ArrayRCP<int> permutation_list( nodes_per_element ); for ( int i = 0; i < (int) nodes_per_element; ++i ) { permutation_list[i] = i; } // Create the mesh container. d_mesh_container = Teuchos::rcp( new Container( node_dim, d_vertices, coords, getTopology(block_topology), nodes_per_element, elements_arcp, connectivity, permutation_list ) ); }
FCPtr BasisEvaluation::getTransformedValuesWithBasisValues(BasisPtr basis, Camellia::EOperator op, constFCPtr referenceValues, int numCells, BasisCache* basisCache) { typedef FunctionSpaceTools fst; // int numCells = cellJacobian.dimension(0); int spaceDim = basisCache->getSpaceDim(); // changed 3-21-16 int componentOfInterest; Camellia::EFunctionSpace fs = basis->functionSpace(); Intrepid::EOperator relatedOp = relatedOperator(op,fs,spaceDim, componentOfInterest); Teuchos::Array<int> dimensions; referenceValues->dimensions(dimensions); dimensions.insert(dimensions.begin(), numCells); Teuchos::RCP<FieldContainer<double> > transformedValues = Teuchos::rcp(new FieldContainer<double>(dimensions)); bool vectorizedBasis = functionSpaceIsVectorized(fs); if (vectorizedBasis && (op == Camellia::OP_VALUE)) { TEUCHOS_TEST_FOR_EXCEPTION( vectorizedBasis && (op == Camellia::OP_VALUE), std::invalid_argument, "Vector HGRAD/HVOL with OP_VALUE not supported by getTransformedValuesWithBasisValues. Please use getTransformedVectorValuesWithComponentBasisValues instead."); } switch(relatedOp) { case(Intrepid::OPERATOR_VALUE): switch(fs) { case Camellia::FUNCTION_SPACE_REAL_SCALAR: // cout << "Reference values for FUNCTION_SPACE_REAL_SCALAR: " << *referenceValues; case Camellia::FUNCTION_SPACE_HGRAD: case Camellia::FUNCTION_SPACE_HGRAD_DISC: fst::HGRADtransformVALUE<double>(*transformedValues,*referenceValues); break; case Camellia::FUNCTION_SPACE_HCURL: case Camellia::FUNCTION_SPACE_HCURL_DISC: fst::HCURLtransformVALUE<double>(*transformedValues,basisCache->getJacobianInv(),*referenceValues); break; case Camellia::FUNCTION_SPACE_HDIV: case Camellia::FUNCTION_SPACE_HDIV_DISC: case Camellia::FUNCTION_SPACE_HDIV_FREE: fst::HDIVtransformVALUE<double>(*transformedValues,basisCache->getJacobian(),basisCache->getJacobianDet(),*referenceValues); break; case Camellia::FUNCTION_SPACE_HVOL: case Camellia::FUNCTION_SPACE_HVOL_SPACE_HGRAD_TIME: case Camellia::FUNCTION_SPACE_HGRAD_SPACE_HVOL_TIME: // { // static bool haveWarned = false; // if (!haveWarned) { // cout << "WARNING: for the moment, switching to the standard HVOLtransformVALUE method.\n"; // haveWarned = true; // } // } // fst::HVOLtransformVALUE<double>(*transformedValues, cellJacobianDet, *referenceValues); // for the moment, use the fact that we know the HVOL basis is always an HGRAD basis: // (I think using the below amounts to solving for the HVOL variables scaled by Jacobian) fst::HGRADtransformVALUE<double>(*transformedValues,*referenceValues); break; default: TEUCHOS_TEST_FOR_EXCEPTION(true,std::invalid_argument, "unhandled transformation"); break; } break; case(Intrepid::OPERATOR_GRAD): case(Intrepid::OPERATOR_D1): switch(fs) { case Camellia::FUNCTION_SPACE_HVOL: case Camellia::FUNCTION_SPACE_HGRAD: case Camellia::FUNCTION_SPACE_HGRAD_DISC: fst::HGRADtransformGRAD<double>(*transformedValues,basisCache->getJacobianInv(),*referenceValues); break; case Camellia::FUNCTION_SPACE_VECTOR_HVOL: case Camellia::FUNCTION_SPACE_VECTOR_HGRAD: case Camellia::FUNCTION_SPACE_VECTOR_HGRAD_DISC: // referenceValues has dimensions (F,P,D1,D2). D1 is our component dimension, and D2 is the one that came from the gradient. // HGRADtransformGRAD expects (F,P,D) for input, and (C,F,P,D) for output. // If we split referenceValues into (F,P,D1=0,D2) and (F,P,D1=1,D2), then we can transform each of those, and then interleave the results… { // block off so we can create new stuff inside the switch case Teuchos::Array<int> dimensions; referenceValues->dimensions(dimensions); int numFields = dimensions[0]; int numPoints = dimensions[1]; int D1 = dimensions[dimensions.size()-2]; int D2 = dimensions[dimensions.size()-1]; dimensions[dimensions.size()-2] = D2; // put D2 in the D1 spot dimensions.pop_back(); // get rid of original D2 FieldContainer<double> refValuesSlice(dimensions); dimensions.insert(dimensions.begin(),numCells); FieldContainer<double> transformedValuesSlice(dimensions); // int numEntriesPerSlice = refValuesSlice.size(); // int numEntriesPerTransformedSlice = transformedValuesSlice.size(); for (int compIndex1=0; compIndex1<D1; compIndex1++) { // could speed the following along by doing the enumeration arithmetic in place... for (int fieldIndex=0; fieldIndex<numFields; fieldIndex++) { for (int ptIndex=0; ptIndex<numPoints; ptIndex++) { for (int compIndex2=0; compIndex2<D2; compIndex2++) { refValuesSlice(fieldIndex,ptIndex,compIndex2) = (*referenceValues)(fieldIndex,ptIndex,compIndex1,compIndex2); } } } // for (int i=0; i<numEntriesPerSlice; i++) { // refValuesSlice[i] = (*referenceValues)[i*D2 + compIndex]; // } fst::HGRADtransformGRAD<double>(transformedValuesSlice,basisCache->getJacobianInv(),refValuesSlice); // could speed the following along by doing the enumeration arithmetic in place... for (int cellIndex=0; cellIndex<numCells; cellIndex++) { for (int fieldIndex=0; fieldIndex<numFields; fieldIndex++) { for (int ptIndex=0; ptIndex<numPoints; ptIndex++) { for (int compIndex2=0; compIndex2<D2; compIndex2++) { (*transformedValues)(cellIndex,fieldIndex,ptIndex,compIndex1,compIndex2) = transformedValuesSlice(cellIndex,fieldIndex,ptIndex,compIndex2); } } } } // for (int i=0; i<numEntriesPerTransformedSlice; i++) { // (*transformedValues)[i*D2 + compIndex] = transformedValuesSlice[i]; // } } } break; default: TEUCHOS_TEST_FOR_EXCEPTION(true,std::invalid_argument, "unhandled transformation"); break; } break; case(Intrepid::OPERATOR_CURL): switch(fs) { case Camellia::FUNCTION_SPACE_HCURL: case Camellia::FUNCTION_SPACE_HCURL_DISC: if (spaceDim == 2) { // TODO: confirm that this is correct // static bool warningIssued = false; // if ( ! warningIssued ) { // cout << "WARNING: for HCURL in 2D, transforming with HVOLtransformVALUE. Need to confirm this is correct.\n"; // warningIssued = true; // } fst::HVOLtransformVALUE<double>(*transformedValues,basisCache->getJacobianDet(), *referenceValues); } else { fst::HCURLtransformCURL<double>(*transformedValues,basisCache->getJacobian(),basisCache->getJacobianDet(),*referenceValues); } break; case Camellia::FUNCTION_SPACE_HGRAD: case Camellia::FUNCTION_SPACE_HGRAD_DISC: // in 2D, HGRADtransformCURL == HDIVtransformVALUE (because curl(H1) --> H(div)) fst::HDIVtransformVALUE<double>(*transformedValues,basisCache->getJacobian(),basisCache->getJacobianDet(),*referenceValues); break; case Camellia::FUNCTION_SPACE_VECTOR_HVOL: case Camellia::FUNCTION_SPACE_VECTOR_HGRAD: case Camellia::FUNCTION_SPACE_VECTOR_HGRAD_DISC: // shouldn't take the transform so late default: TEUCHOS_TEST_FOR_EXCEPTION(true,std::invalid_argument, "unhandled transformation"); break; } break; case(Intrepid::OPERATOR_DIV): switch(fs) { case Camellia::FUNCTION_SPACE_HDIV: case Camellia::FUNCTION_SPACE_HDIV_DISC: case Camellia::FUNCTION_SPACE_HDIV_FREE: fst::HDIVtransformDIV<double>(*transformedValues,basisCache->getJacobianDet(),*referenceValues); break; case Camellia::FUNCTION_SPACE_VECTOR_HVOL: case Camellia::FUNCTION_SPACE_VECTOR_HGRAD: case Camellia::FUNCTION_SPACE_VECTOR_HGRAD_DISC: // shouldn't take the transform so late default: TEUCHOS_TEST_FOR_EXCEPTION(true,std::invalid_argument, "unhandled transformation"); break; } break; case(Intrepid::OPERATOR_D2): switch(fs) { case Camellia::FUNCTION_SPACE_HVOL: case Camellia::FUNCTION_SPACE_HGRAD: case Camellia::FUNCTION_SPACE_HGRAD_DISC: { // first term in the sum is: // J^{-1} * OPD2 * J^{-T} // where J^{-1} is the inverse Jacabian, and OPD2 is the matrix of reference-space values formed from OP_D2 const FieldContainer<double> *J_inv = &basisCache->getJacobianInv(); transformedValues->initialize(0.0); int basisCardinality = basis->getCardinality(); Teuchos::Array<int> multiplicities(spaceDim); Teuchos::Array<int> multiplicitiesTransformed(spaceDim); int dkCardinality = Intrepid::getDkCardinality(Intrepid::OPERATOR_D2, spaceDim); int numPoints = referenceValues->dimension(1); for (int cellOrdinal=0; cellOrdinal<numCells; cellOrdinal++) { for (int fieldOrdinal=0; fieldOrdinal<basisCardinality; fieldOrdinal++) { for (int pointOrdinal=0; pointOrdinal<numPoints; pointOrdinal++) { for (int dkOrdinal=0; dkOrdinal<dkCardinality; dkOrdinal++) // ref values dkOrdinal { double refValue = (*referenceValues)(fieldOrdinal,pointOrdinal,dkOrdinal); Intrepid::getDkMultiplicities(multiplicities, dkOrdinal, Intrepid::OPERATOR_D2, spaceDim); int k,l; // ref space coordinate directions for refValue (columns in J_inv) getD2_ij_FromMultiplicities(k,l,multiplicities); for (int dkOrdinalTransformed=0; dkOrdinalTransformed<dkCardinality; dkOrdinalTransformed++) // physical values dkOrdinal { Intrepid::getDkMultiplicities(multiplicitiesTransformed, dkOrdinalTransformed, Intrepid::OPERATOR_D2, spaceDim); int i,j; // physical space coordinate directions for refValue (rows in J_inv) getD2_ij_FromMultiplicities(i,j,multiplicitiesTransformed); double J_inv_ik = (*J_inv)(cellOrdinal,pointOrdinal,i,k); double J_inv_jl = (*J_inv)(cellOrdinal,pointOrdinal,j,l); (*transformedValues)(cellOrdinal,fieldOrdinal,pointOrdinal,dkOrdinalTransformed) += refValue * J_inv_ik * J_inv_jl; } } } } } // do we need the second term in the sum? (So far, we don't support this) if (!basisCache->neglectHessian()) { // then we need to do include the gradient of the basis times the (inverse) of the Hessian // this seems complicated, and we don't need it for computing the Laplacian in physical space // (at least not unless we have curvilinear geometry) so we don't support it for now... TEUCHOS_TEST_FOR_EXCEPTION(!basisCache->neglectHessian(), std::invalid_argument, "Support for the Hessian of the reference-to-physical mapping not yet implemented."); } } break; default: TEUCHOS_TEST_FOR_EXCEPTION(true,std::invalid_argument, "unhandled transformation"); break; } break; default: TEUCHOS_TEST_FOR_EXCEPTION(true,std::invalid_argument, "unhandled transformation"); break; } FCPtr result = getComponentOfInterest(transformedValues,op,fs,componentOfInterest); if ( result.get() == 0 ) { result = transformedValues; } return result; }
ATO::StiffnessObjectiveBase<EvalT, Traits>:: StiffnessObjectiveBase(Teuchos::ParameterList& p, const Teuchos::RCP<Albany::Layouts>& dl, const Albany::MeshSpecsStruct* meshSpecs) : qp_weights ("Weights", dl->qp_scalar ), BF ("BF", dl->node_qp_scalar) { Teuchos::ParameterList* responseParams = p.get<Teuchos::ParameterList*>("Parameter List"); elementBlockName = meshSpecs->ebName; m_excludeBlock = false; if(responseParams->isType<Teuchos::Array<std::string>>("Blocks")){ Teuchos::Array<std::string> blocks = responseParams->get<Teuchos::Array<std::string>>("Blocks"); if(find(blocks.begin(),blocks.end(),elementBlockName) == blocks.end()){ m_excludeBlock = true; stiffness_objective_tag = Teuchos::rcp(new PHX::Tag<ScalarT>(className, dl->dummy)); this->addEvaluatedField(*stiffness_objective_tag); return; } } ATO::PenaltyModelFactory<ScalarT> penaltyFactory; penaltyModel = penaltyFactory.create(p, dl, elementBlockName); Teuchos::RCP<Teuchos::ParameterList> paramsFromProblem = p.get< Teuchos::RCP<Teuchos::ParameterList> >("Parameters From Problem"); topologies = paramsFromProblem->get<Teuchos::RCP<TopologyArray> >("Topologies"); int nTopos = topologies->size(); FName = responseParams->get<std::string>("Response Name"); std::string dFdpBaseName = responseParams->get<std::string>("Response Derivative Name"); dFdpNames.resize(nTopos); for(int itopo=0; itopo<nTopos; itopo++){ dFdpNames[itopo] = Albany::strint(dFdpBaseName,itopo); } this->pStateMgr = p.get< Albany::StateManager* >("State Manager Ptr"); this->pStateMgr->registerStateVariable(FName, dl->workset_scalar, dl->dummy, "all", "scalar", 0.0, false, false); for(int itopo=0; itopo<nTopos; itopo++){ this->pStateMgr->registerStateVariable(dFdpNames[itopo], dl->node_scalar, dl->dummy, "all", "scalar", 0.0, false, false); } this->addDependentField(qp_weights); this->addDependentField(BF); Teuchos::Array< PHX::MDField<ScalarT> > depFields; penaltyModel->getDependentFields(depFields); int nFields = depFields.size(); for(int ifield=0; ifield<nFields; ifield++) this->addDependentField(depFields[ifield].fieldTag()); stiffness_objective_tag = Teuchos::rcp(new PHX::Tag<ScalarT>(className, dl->dummy)); this->addEvaluatedField(*stiffness_objective_tag); }
void Export<LocalOrdinal,GlobalOrdinal,Node>::setupRemote(Teuchos::Array<GlobalOrdinal> & exportGIDs) { using std::endl; const Map<LocalOrdinal,GlobalOrdinal,Node>& target = * (getTargetMap ()); const int myRank = target.getComm ()->getRank (); if (! out_.is_null ()) { out_->pushTab (); } if (debug_) { std::ostringstream os; os << myRank << ": Export::setupRemote" << endl; *out_ << os.str (); } if (! out_.is_null ()) { out_->pushTab (); } // Sort exportPIDs_ in ascending order, and apply the same // permutation to exportGIDs_ and exportLIDs_. This ensures that // exportPIDs_[i], exportGIDs_[i], and exportLIDs_[i] all // refer to the same thing. sort3 (ExportData_->exportPIDs_.begin(), ExportData_->exportPIDs_.end(), exportGIDs.begin(), ExportData_->exportLIDs_.begin()); if (debug_) { std::ostringstream os; os << myRank << ": Export::setupRemote: Calling createFromSends" << endl; *out_ << os.str (); } // Construct the list of entries that calling image needs to send // as a result of everyone asking for what it needs to receive. // // mfh 05 Jan 2012: I understand the above comment as follows: // Construct the communication plan from the list of image IDs to // which we need to send. size_t numRemoteIDs; numRemoteIDs = ExportData_->distributor_.createFromSends (ExportData_->exportPIDs_ ()); if (debug_) { std::ostringstream os; os << myRank << ": Export::setupRemote: Calling doPostsAndWaits" << endl; *out_ << os.str (); } // Use the communication plan with ExportGIDs to find out who is // sending to us and get the proper ordering of GIDs for incoming // remote entries (these will be converted to LIDs when done). Array<GlobalOrdinal> remoteGIDs (numRemoteIDs); ExportData_->distributor_.doPostsAndWaits (exportGIDs().getConst (), 1, remoteGIDs()); // Remote (incoming) IDs come in as GIDs; convert to LIDs. LIDs // tell this process where to store the incoming remote data. ExportData_->remoteLIDs_.resize (numRemoteIDs); { typename Array<GlobalOrdinal>::const_iterator i = remoteGIDs.begin(); typename Array<LocalOrdinal>::iterator j = ExportData_->remoteLIDs_.begin(); while (i != remoteGIDs.end()) { *j++ = target.getLocalElement(*i++); } } if (! out_.is_null ()) { out_->popTab (); } if (debug_) { std::ostringstream os; os << myRank << ": Export::setupRemote: done" << endl; *out_ << os.str (); } if (! out_.is_null ()) { out_->popTab (); } }
//! Iterator pointing to beginning of array const_iterator begin() const { return const_iterator(indices.begin(), values.begin()); }
bool MeshTestUtility::neighborBasesAgreeOnSides(Teuchos::RCP<Mesh> mesh, Epetra_MultiVector &globalSolutionCoefficients) { bool success = true; MeshTopologyViewPtr meshTopo = mesh->getTopology(); int spaceDim = meshTopo->getDimension(); set<IndexType> activeCellIndices = meshTopo->getActiveCellIndices(); for (set<IndexType>::iterator cellIt=activeCellIndices.begin(); cellIt != activeCellIndices.end(); cellIt++) { IndexType cellIndex = *cellIt; CellPtr cell = meshTopo->getCell(cellIndex); BasisCachePtr fineCellBasisCache = BasisCache::basisCacheForCell(mesh, cellIndex); ElementTypePtr fineElemType = mesh->getElementType(cellIndex); DofOrderingPtr fineElemTrialOrder = fineElemType->trialOrderPtr; FieldContainer<double> fineSolutionCoefficients(fineElemTrialOrder->totalDofs()); mesh->globalDofAssignment()->interpretGlobalCoefficients(cellIndex, fineSolutionCoefficients, globalSolutionCoefficients); // if ((cellIndex==0) || (cellIndex==2)) { // cout << "MeshTestUtility: local coefficients for cell " << cellIndex << ":\n" << fineSolutionCoefficients; // } unsigned sideCount = cell->getSideCount(); for (unsigned sideOrdinal=0; sideOrdinal<sideCount; sideOrdinal++) { FieldContainer<double> fineSideRefPoints, fineCellRefPoints, coarseSideRefPoints, coarseCellRefPoints; bool hasCoarserNeighbor = determineRefTestPointsForNeighbors(meshTopo, cell, sideOrdinal, fineSideRefPoints, fineCellRefPoints, coarseSideRefPoints, coarseCellRefPoints); if (!hasCoarserNeighbor) continue; pair<GlobalIndexType, unsigned> neighborInfo = cell->getNeighborInfo(sideOrdinal, meshTopo); CellPtr neighborCell = meshTopo->getCell(neighborInfo.first); unsigned numTestPoints = coarseCellRefPoints.dimension(0); // cout << "testing neighbor agreement between cell " << cellIndex << " and " << neighborCell->cellIndex() << endl; // if we get here, the cell has a neighbor on this side, and is at least as fine as that neighbor. BasisCachePtr fineSideBasisCache = fineCellBasisCache->getSideBasisCache(sideOrdinal); fineCellBasisCache->setRefCellPoints(fineCellRefPoints); BasisCachePtr coarseCellBasisCache = BasisCache::basisCacheForCell(mesh, neighborInfo.first); BasisCachePtr coarseSideBasisCache = coarseCellBasisCache->getSideBasisCache(neighborInfo.second); coarseCellBasisCache->setRefCellPoints(coarseCellRefPoints); bool hasSidePoints = (fineSideRefPoints.size() > 0); if (hasSidePoints) { fineSideBasisCache->setRefCellPoints(fineSideRefPoints); coarseSideBasisCache->setRefCellPoints(coarseSideRefPoints); } // sanity check: do physical points match? FieldContainer<double> fineCellPhysicalCubaturePoints = fineCellBasisCache->getPhysicalCubaturePoints(); FieldContainer<double> coarseCellPhysicalCubaturePoints = coarseCellBasisCache->getPhysicalCubaturePoints(); double tol = 1e-14; double maxDiff = 0; if (! fcsAgree(coarseCellPhysicalCubaturePoints, fineCellPhysicalCubaturePoints, tol, maxDiff) ) { cout << "ERROR: MeshTestUtility::neighborBasesAgreeOnSides internal error: fine and coarse cell cubature points do not agree.\n"; success = false; continue; } if (hasSidePoints) { FieldContainer<double> fineSidePhysicalCubaturePoints = fineSideBasisCache->getPhysicalCubaturePoints(); FieldContainer<double> coarseSidePhysicalCubaturePoints = coarseSideBasisCache->getPhysicalCubaturePoints(); double tol = 1e-14; double maxDiff = 0; if (! fcsAgree(fineSidePhysicalCubaturePoints, fineCellPhysicalCubaturePoints, tol, maxDiff) ) { cout << "ERROR: MeshTestUtility::neighborBasesAgreeOnSides internal error: fine side and cell cubature points do not agree.\n"; success = false; continue; } if (! fcsAgree(coarseSidePhysicalCubaturePoints, coarseCellPhysicalCubaturePoints, tol, maxDiff) ) { cout << "ERROR: MeshTestUtility::neighborBasesAgreeOnSides internal error: coarse side and cell cubature points do not agree.\n"; success = false; continue; } if (! fcsAgree(coarseSidePhysicalCubaturePoints, fineSidePhysicalCubaturePoints, tol, maxDiff) ) { cout << "ERROR: MeshTestUtility::neighborBasesAgreeOnSides internal error: fine and coarse side cubature points do not agree.\n"; success = false; continue; } } ElementTypePtr coarseElementType = mesh->getElementType(neighborInfo.first); DofOrderingPtr coarseElemTrialOrder = coarseElementType->trialOrderPtr; FieldContainer<double> coarseSolutionCoefficients(coarseElemTrialOrder->totalDofs()); mesh->globalDofAssignment()->interpretGlobalCoefficients(neighborInfo.first, coarseSolutionCoefficients, globalSolutionCoefficients); set<int> varIDs = fineElemTrialOrder->getVarIDs(); for (set<int>::iterator varIt = varIDs.begin(); varIt != varIDs.end(); varIt++) { int varID = *varIt; // cout << "MeshTestUtility: varID " << varID << ":\n"; bool isTraceVar = mesh->bilinearForm()->isFluxOrTrace(varID); BasisPtr fineBasis, coarseBasis; BasisCachePtr fineCache, coarseCache; if (isTraceVar) { if (! hasSidePoints) continue; // then nothing to do for traces fineBasis = fineElemTrialOrder->getBasis(varID, sideOrdinal); coarseBasis = coarseElemTrialOrder->getBasis(varID, neighborInfo.second); fineCache = fineSideBasisCache; coarseCache = coarseSideBasisCache; } else { fineBasis = fineElemTrialOrder->getBasis(varID); coarseBasis = coarseElemTrialOrder->getBasis(varID); fineCache = fineCellBasisCache; coarseCache = coarseCellBasisCache; Camellia::EFunctionSpace fs = fineBasis->functionSpace(); if ((fs == Camellia::FUNCTION_SPACE_HVOL) || (fs == Camellia::FUNCTION_SPACE_VECTOR_HVOL) || (fs == Camellia::FUNCTION_SPACE_TENSOR_HVOL)) { // volume L^2 basis: no continuities expected... continue; } } FieldContainer<double> localValuesFine = *fineCache->getTransformedValues(fineBasis, OP_VALUE); FieldContainer<double> localValuesCoarse = *coarseCache->getTransformedValues(coarseBasis, OP_VALUE); bool scalarValued = (localValuesFine.rank() == 3); // the following used if vector or tensor-valued: Teuchos::Array<int> valueDim; unsigned componentsPerValue = 1; FieldContainer<double> valueContainer; // just used for enumeration computation... if (!scalarValued) { localValuesFine.dimensions(valueDim); // clear first three: valueDim.erase(valueDim.begin()); valueDim.erase(valueDim.begin()); valueDim.erase(valueDim.begin()); valueContainer.resize(valueDim); componentsPerValue = valueContainer.size(); } // if (localValuesFine.rank() != 3) { // cout << "WARNING: MeshTestUtility::neighborBasesAgreeOnSides() only supports scalar-valued bases right now. Skipping check for varID " << varID << endl; // continue; // } FieldContainer<double> localPointValuesFine(fineElemTrialOrder->totalDofs()); FieldContainer<double> localPointValuesCoarse(coarseElemTrialOrder->totalDofs()); for (int valueComponentOrdinal=0; valueComponentOrdinal<componentsPerValue; valueComponentOrdinal++) { Teuchos::Array<int> valueMultiIndex(valueContainer.rank()); if (!scalarValued) valueContainer.getMultiIndex(valueMultiIndex, valueComponentOrdinal); Teuchos::Array<int> localValuesMultiIndex(localValuesFine.rank()); for (int r=0; r<valueMultiIndex.size(); r++) { localValuesMultiIndex[r+3] = valueMultiIndex[r]; } for (int ptOrdinal=0; ptOrdinal<numTestPoints; ptOrdinal++) { localPointValuesCoarse.initialize(0); localPointValuesFine.initialize(0); localValuesMultiIndex[2] = ptOrdinal; double fineSolutionValue = 0, coarseSolutionValue = 0; for (int basisOrdinal=0; basisOrdinal < fineBasis->getCardinality(); basisOrdinal++) { int fineDofIndex; if (isTraceVar) fineDofIndex = fineElemTrialOrder->getDofIndex(varID, basisOrdinal, sideOrdinal); else fineDofIndex = fineElemTrialOrder->getDofIndex(varID, basisOrdinal); if (scalarValued) { localPointValuesFine(fineDofIndex) = localValuesFine(0,basisOrdinal,ptOrdinal); } else { localValuesMultiIndex[1] = basisOrdinal; localPointValuesFine(fineDofIndex) = localValuesFine.getValue(localValuesMultiIndex); } fineSolutionValue += fineSolutionCoefficients(fineDofIndex) * localPointValuesFine(fineDofIndex); } for (int basisOrdinal=0; basisOrdinal < coarseBasis->getCardinality(); basisOrdinal++) { int coarseDofIndex; if (isTraceVar) coarseDofIndex = coarseElemTrialOrder->getDofIndex(varID, basisOrdinal, neighborInfo.second); else coarseDofIndex = coarseElemTrialOrder->getDofIndex(varID, basisOrdinal); if (scalarValued) { localPointValuesCoarse(coarseDofIndex) = localValuesCoarse(0,basisOrdinal,ptOrdinal); } else { localValuesMultiIndex[1] = basisOrdinal; localPointValuesCoarse(coarseDofIndex) = localValuesCoarse.getValue(localValuesMultiIndex); } coarseSolutionValue += coarseSolutionCoefficients(coarseDofIndex) * localPointValuesCoarse(coarseDofIndex); } if (abs(coarseSolutionValue - fineSolutionValue) > 1e-13) { success = false; cout << "coarseSolutionValue (" << coarseSolutionValue << ") and fineSolutionValue (" << fineSolutionValue << ") differ by " << abs(coarseSolutionValue - fineSolutionValue); cout << " at point " << ptOrdinal << " for varID " << varID << ". "; cout << "This may be an indication that something is amiss with the global-to-local map.\n"; } else { // // DEBUGGING: // cout << "solution value at point ("; // for (int d=0; d<spaceDim-1; d++) { // cout << fineSidePhysicalCubaturePoints(0,ptOrdinal,d) << ", "; // } // cout << fineSidePhysicalCubaturePoints(0,ptOrdinal,spaceDim-1) << "): "; // cout << coarseSolutionValue << endl; } FieldContainer<double> globalValuesFromFine, globalValuesFromCoarse; FieldContainer<GlobalIndexType> globalDofIndicesFromFine, globalDofIndicesFromCoarse; mesh->globalDofAssignment()->interpretLocalData(cellIndex, localPointValuesFine, globalValuesFromFine, globalDofIndicesFromFine); mesh->globalDofAssignment()->interpretLocalData(neighborInfo.first, localPointValuesCoarse, globalValuesFromCoarse, globalDofIndicesFromCoarse); std::map<GlobalIndexType, double> fineValuesMap; std::map<GlobalIndexType, double> coarseValuesMap; for (int i=0; i<globalDofIndicesFromCoarse.size(); i++) { GlobalIndexType globalDofIndex = globalDofIndicesFromCoarse[i]; coarseValuesMap[globalDofIndex] = globalValuesFromCoarse[i]; } double maxDiff = 0; for (int i=0; i<globalDofIndicesFromFine.size(); i++) { GlobalIndexType globalDofIndex = globalDofIndicesFromFine[i]; fineValuesMap[globalDofIndex] = globalValuesFromFine[i]; double diff = abs( fineValuesMap[globalDofIndex] - coarseValuesMap[globalDofIndex]); maxDiff = std::max(diff, maxDiff); if (diff > tol) { success = false; cout << "interpreted fine and coarse disagree at point ("; for (int d=0; d<spaceDim; d++) { cout << fineCellPhysicalCubaturePoints(0,ptOrdinal,d); if (d==spaceDim-1) cout << ").\n"; else cout << ", "; } } } if (maxDiff > tol) { cout << "maxDiff: " << maxDiff << endl; cout << "globalValuesFromFine:\n" << globalValuesFromFine; cout << "globalValuesFromCoarse:\n" << globalValuesFromCoarse; cout << "globalDofIndicesFromFine:\n" << globalDofIndicesFromFine; cout << "globalDofIndicesFromCoarse:\n" << globalDofIndicesFromCoarse; continue; // only worth testing further if we passed the above } } } } } } // cout << "Completed neighborBasesAgreeOnSides.\n"; return success; }
FCPtr BasisEvaluation::getTransformedValuesWithBasisValues(BasisPtr basis, Camellia::EOperator op, int spaceDim, constFCPtr referenceValues, int numCells, const FieldContainer<double> &cellJacobian, const FieldContainer<double> &cellJacobianInv, const FieldContainer<double> &cellJacobianDet) { typedef FunctionSpaceTools fst; // int numCells = cellJacobian.dimension(0); // int spaceDim = basis->domainTopology()->getDimension(); // changed 2/18/15 // // 6-16-14 NVR: getting the spaceDim from cellJacobian's dimensioning is the way we've historically done it. // // I think it might be better to do this using basis->domainTopology() generally, but for now we only make the // // switch in case the domain topology is a Node. // if (basis->domainTopology()->getDimension() == 0) { // spaceDim = 0; // } else { // spaceDim = cellJacobian.dimension(2); // } int componentOfInterest; Camellia::EFunctionSpace fs = basis->functionSpace(); Intrepid::EOperator relatedOp = relatedOperator(op,fs,spaceDim, componentOfInterest); Teuchos::Array<int> dimensions; referenceValues->dimensions(dimensions); dimensions.insert(dimensions.begin(), numCells); Teuchos::RCP<FieldContainer<double> > transformedValues = Teuchos::rcp(new FieldContainer<double>(dimensions)); bool vectorizedBasis = functionSpaceIsVectorized(fs); if (vectorizedBasis && (op == Camellia::OP_VALUE)) { TEUCHOS_TEST_FOR_EXCEPTION( vectorizedBasis && (op == Camellia::OP_VALUE), std::invalid_argument, "Vector HGRAD/HVOL with OP_VALUE not supported by getTransformedValuesWithBasisValues. Please use getTransformedVectorValuesWithComponentBasisValues instead."); } switch(relatedOp) { case(Intrepid::OPERATOR_VALUE): switch(fs) { case Camellia::FUNCTION_SPACE_REAL_SCALAR: // cout << "Reference values for FUNCTION_SPACE_REAL_SCALAR: " << *referenceValues; case Camellia::FUNCTION_SPACE_HGRAD: case Camellia::FUNCTION_SPACE_HGRAD_DISC: fst::HGRADtransformVALUE<double>(*transformedValues,*referenceValues); break; case Camellia::FUNCTION_SPACE_HCURL: case Camellia::FUNCTION_SPACE_HCURL_DISC: fst::HCURLtransformVALUE<double>(*transformedValues,cellJacobianInv,*referenceValues); break; case Camellia::FUNCTION_SPACE_HDIV: case Camellia::FUNCTION_SPACE_HDIV_DISC: case Camellia::FUNCTION_SPACE_HDIV_FREE: fst::HDIVtransformVALUE<double>(*transformedValues,cellJacobian,cellJacobianDet,*referenceValues); break; case Camellia::FUNCTION_SPACE_HVOL: case Camellia::FUNCTION_SPACE_HVOL_SPACE_HGRAD_TIME: case Camellia::FUNCTION_SPACE_HGRAD_SPACE_HVOL_TIME: // { // static bool haveWarned = false; // if (!haveWarned) { // cout << "WARNING: for the moment, switching to the standard HVOLtransformVALUE method.\n"; // haveWarned = true; // } // } // fst::HVOLtransformVALUE<double>(*transformedValues, cellJacobianDet, *referenceValues); // for the moment, use the fact that we know the HVOL basis is always an HGRAD basis: // (I think using the below amounts to solving for the HVOL variables scaled by Jacobian) fst::HGRADtransformVALUE<double>(*transformedValues,*referenceValues); break; default: TEUCHOS_TEST_FOR_EXCEPTION(true,std::invalid_argument, "unhandled transformation"); break; } break; case(Intrepid::OPERATOR_GRAD): switch(fs) { case Camellia::FUNCTION_SPACE_HVOL: case Camellia::FUNCTION_SPACE_HGRAD: case Camellia::FUNCTION_SPACE_HGRAD_DISC: fst::HGRADtransformGRAD<double>(*transformedValues,cellJacobianInv,*referenceValues); break; case Camellia::FUNCTION_SPACE_VECTOR_HVOL: case Camellia::FUNCTION_SPACE_VECTOR_HGRAD: case Camellia::FUNCTION_SPACE_VECTOR_HGRAD_DISC: // referenceValues has dimensions (F,P,D1,D2). D1 is our component dimension, and D2 is the one that came from the gradient. // HGRADtransformGRAD expects (F,P,D) for input, and (C,F,P,D) for output. // If we split referenceValues into (F,P,D1=0,D2) and (F,P,D1=1,D2), then we can transform each of those, and then interleave the results… { // block off so we can create new stuff inside the switch case Teuchos::Array<int> dimensions; referenceValues->dimensions(dimensions); int numFields = dimensions[0]; int numPoints = dimensions[1]; int D1 = dimensions[dimensions.size()-2]; int D2 = dimensions[dimensions.size()-1]; dimensions[dimensions.size()-2] = D2; // put D2 in the D1 spot dimensions.pop_back(); // get rid of original D2 FieldContainer<double> refValuesSlice(dimensions); dimensions.insert(dimensions.begin(),numCells); FieldContainer<double> transformedValuesSlice(dimensions); // int numEntriesPerSlice = refValuesSlice.size(); // int numEntriesPerTransformedSlice = transformedValuesSlice.size(); for (int compIndex1=0; compIndex1<D1; compIndex1++) { // could speed the following along by doing the enumeration arithmetic in place... for (int fieldIndex=0; fieldIndex<numFields; fieldIndex++) { for (int ptIndex=0; ptIndex<numPoints; ptIndex++) { for (int compIndex2=0; compIndex2<D2; compIndex2++) { refValuesSlice(fieldIndex,ptIndex,compIndex2) = (*referenceValues)(fieldIndex,ptIndex,compIndex1,compIndex2); } } } // for (int i=0; i<numEntriesPerSlice; i++) { // refValuesSlice[i] = (*referenceValues)[i*D2 + compIndex]; // } fst::HGRADtransformGRAD<double>(transformedValuesSlice,cellJacobianInv,refValuesSlice); // could speed the following along by doing the enumeration arithmetic in place... for (int cellIndex=0; cellIndex<numCells; cellIndex++) { for (int fieldIndex=0; fieldIndex<numFields; fieldIndex++) { for (int ptIndex=0; ptIndex<numPoints; ptIndex++) { for (int compIndex2=0; compIndex2<D2; compIndex2++) { (*transformedValues)(cellIndex,fieldIndex,ptIndex,compIndex1,compIndex2) = transformedValuesSlice(cellIndex,fieldIndex,ptIndex,compIndex2); } } } } // for (int i=0; i<numEntriesPerTransformedSlice; i++) { // (*transformedValues)[i*D2 + compIndex] = transformedValuesSlice[i]; // } } } break; default: TEUCHOS_TEST_FOR_EXCEPTION(true,std::invalid_argument, "unhandled transformation"); break; } break; case(Intrepid::OPERATOR_CURL): switch(fs) { case Camellia::FUNCTION_SPACE_HCURL: case Camellia::FUNCTION_SPACE_HCURL_DISC: if (spaceDim == 2) { // TODO: confirm that this is correct // static bool warningIssued = false; // if ( ! warningIssued ) { // cout << "WARNING: for HCURL in 2D, transforming with HVOLtransformVALUE. Need to confirm this is correct.\n"; // warningIssued = true; // } fst::HVOLtransformVALUE<double>(*transformedValues, cellJacobianDet, *referenceValues); } else { fst::HCURLtransformCURL<double>(*transformedValues,cellJacobian,cellJacobianDet,*referenceValues); } break; case Camellia::FUNCTION_SPACE_HGRAD: case Camellia::FUNCTION_SPACE_HGRAD_DISC: // in 2D, HGRADtransformCURL == HDIVtransformVALUE (because curl(H1) --> H(div)) fst::HDIVtransformVALUE<double>(*transformedValues,cellJacobian,cellJacobianDet,*referenceValues); break; case Camellia::FUNCTION_SPACE_VECTOR_HVOL: case Camellia::FUNCTION_SPACE_VECTOR_HGRAD: case Camellia::FUNCTION_SPACE_VECTOR_HGRAD_DISC: // shouldn't take the transform so late default: TEUCHOS_TEST_FOR_EXCEPTION(true,std::invalid_argument, "unhandled transformation"); break; } break; case(Intrepid::OPERATOR_DIV): switch(fs) { case Camellia::FUNCTION_SPACE_HDIV: case Camellia::FUNCTION_SPACE_HDIV_DISC: case Camellia::FUNCTION_SPACE_HDIV_FREE: fst::HDIVtransformDIV<double>(*transformedValues,cellJacobianDet,*referenceValues); break; case Camellia::FUNCTION_SPACE_VECTOR_HVOL: case Camellia::FUNCTION_SPACE_VECTOR_HGRAD: case Camellia::FUNCTION_SPACE_VECTOR_HGRAD_DISC: // shouldn't take the transform so late default: TEUCHOS_TEST_FOR_EXCEPTION(true,std::invalid_argument, "unhandled transformation"); break; } break; default: TEUCHOS_TEST_FOR_EXCEPTION(true,std::invalid_argument, "unhandled transformation"); break; } FCPtr result = getComponentOfInterest(transformedValues,op,fs,componentOfInterest); if ( result.get() == 0 ) { result = transformedValues; } return result; }