// Exec_SortEnsembleData::Execute() Exec::RetType Exec_SortEnsembleData::Execute(CpptrajState& State, ArgList& argIn) { debug_ = State.Debug(); DataSetList setsToSort; std::string dsarg = argIn.GetStringNext(); while (!dsarg.empty()) { setsToSort += State.DSL().GetMultipleSets( dsarg ); dsarg = argIn.GetStringNext(); } int err = 0; # ifdef MPI // For now, require ensemble mode in parallel. if (!Parallel::EnsembleIsSetup()) { rprinterr("Error: Data set ensemble sort requires ensemble mode in parallel.\n"); return CpptrajState::ERR; } // Only TrajComm masters have complete data. if (Parallel::TrajComm().Master()) { comm_ = Parallel::MasterComm(); # endif DataSetList OutputSets; err = SortData( setsToSort, OutputSets ); if (err == 0) { // Remove unsorted sets. for (DataSetList::const_iterator ds = setsToSort.begin(); ds != setsToSort.end(); ++ds) State.DSL().RemoveSet( *ds ); // Add sorted sets. for (DataSetList::const_iterator ds = OutputSets.begin(); ds != OutputSets.end(); ++ds) State.DSL().AddSet( *ds ); // Since sorted sets have been transferred to master DSL, OutputSets now // just has copies. OutputSets.SetHasCopies( true ); mprintf("\tSorted sets:\n"); OutputSets.List(); } # ifdef MPI } if (Parallel::World().CheckError( err )) # else if (err != 0) # endif return CpptrajState::ERR; return CpptrajState::OK; }
// Exec_SortEnsembleData::SortData() int Exec_SortEnsembleData::SortData(DataSetList const& setsToSort, DataSetList& OutputSets) const { int err = 0; if (setsToSort.empty()) { rprinterr("Error: No sets selected.\n"); err = 1; } if (CheckError(err)) return 1; mprintf("\tSorting the following sets:\n"); setsToSort.List(); # ifdef MPI // Number of sets to sort should be equal to # members I am responsible for. if (Parallel::N_Ens_Members() != (int)setsToSort.size()) { rprinterr("Internal Error: Number of ensemble members (%i) != # sets to sort (%zu)\n", Parallel::N_Ens_Members(), setsToSort.size()); return 1; } # endif DataSet::DataType dtype = setsToSort[0]->Type(); unsigned int maxSize = 0; for (DataSetList::const_iterator ds = setsToSort.begin(); ds != setsToSort.end(); ++ds) { if ((*ds)->Size() < 1) { //TODO check sizes match rprinterr("Error: Set '%s' is empty.\n", (*ds)->legend()); err = 1; break; } if (ds == setsToSort.begin()) maxSize = (*ds)->Size(); else if ((*ds)->Size() < maxSize) { rprintf("Warning: Set '%s' has fewer frames (%zu) than previous set(s) (%u)\n" "Warning: Only using the first %zu frames of all sets.\n", (*ds)->legend(), (*ds)->Size(), maxSize, (*ds)->Size()); maxSize = (unsigned int)(*ds)->Size(); } else if ((*ds)->Size() > maxSize) { rprintf("Warning: Set '%s' has more frames (%zu) than previous set(s) (%u)\n" "Warning: Only using the first %u frames of all sets.\n", (*ds)->legend(), (*ds)->Size(), maxSize, maxSize); } if (dtype != (*ds)->Type()) { rprinterr("Error: Set '%s' has different type than first set.\n", (*ds)->legend()); err = 1; break; } } if (CheckError(err)) return 1; # ifdef MPI unsigned int threadSize = maxSize; comm_.AllReduce( &maxSize, &threadSize, 1, MPI_UNSIGNED, MPI_MIN ); typedef std::vector<int> Iarray; Iarray Dtypes( comm_.Size(), -1 ); if ( comm_.AllGather( &dtype, 1, MPI_INT, &Dtypes[0] ) ) return 1; for (int rank = 1; rank < comm_.Size(); rank++) if (Dtypes[0] != Dtypes[rank]) { rprinterr("Error: Set types on rank %i do not match types on rank 0.\n", rank); err = 1; break; } if (comm_.CheckError( err )) return 1; # endif // Only work for pH data for now. if (dtype != DataSet::PH_EXPL && dtype != DataSet::PH_IMPL) { rprinterr("Error: Only works for pH REMD data for now.\n"); return 1; } err = Sort_pH_Data( setsToSort, OutputSets, maxSize ); return err; }