• Main Page
  • Related Pages
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

QCAD_MultiSolutionObserver.cpp

Go to the documentation of this file.
00001 //*****************************************************************//
00002 //    Albany 2.0:  Copyright 2012 Sandia Corporation               //
00003 //    This Software is released under the BSD license detailed     //
00004 //    in the file "license.txt" in the top-level Albany directory  //
00005 //*****************************************************************//
00006 
00007 #include "Teuchos_RCP.hpp"
00008 #include "Teuchos_TestForException.hpp"
00009 #include "Epetra_Export.h"
00010 #include "Epetra_Vector.h"
00011 #include "Epetra_MultiVector.h"
00012 
00013 #include "Albany_StateInfoStruct.hpp"
00014 #include "QCAD_MultiSolutionObserver.hpp"
00015 
00016 //For creating discretiation object
00017 #include "Albany_DiscretizationFactory.hpp"
00018 #include "Albany_StateInfoStruct.hpp"
00019 #include "Albany_AbstractFieldContainer.hpp"
00020 #include "Piro_NullSpaceUtils.hpp"
00021 
00022 
00023 
00025 // OBSERVER
00027 
00028 QCAD::MultiSolution_Observer::MultiSolution_Observer(const Teuchos::RCP<Albany::Application>& app,
00029                  const Teuchos::RCP<Teuchos::ParameterList>& params)
00030 {
00031   rootParams = Teuchos::createParameterList("Multi Solution Observer Discretization Parameters");
00032   Teuchos::ParameterList& discList = rootParams->sublist("Discretization", false);
00033   if(params->isSublist("Discretization"))
00034     discList.setParameters(params->sublist("Discretization")); //copy discretization sublist of app
00035 
00036   apps.push_back(app);
00037 }
00038 
00039 QCAD::MultiSolution_Observer::MultiSolution_Observer(const Teuchos::RCP<Albany::Application>& app1,
00040                  const Teuchos::RCP<Albany::Application>& app2,
00041                  const Teuchos::RCP<Teuchos::ParameterList>& params)
00042 {
00043   rootParams = Teuchos::createParameterList("Multi Solution Observer Discretization Parameters");
00044   Teuchos::ParameterList& discList = rootParams->sublist("Discretization", false);
00045   if(params->isSublist("Discretization"))
00046     discList.setParameters(params->sublist("Discretization")); //copy discretization sublist of app
00047 
00048   apps.push_back(app1);
00049   apps.push_back(app2);
00050 }
00051 
00052 
00053 void QCAD::MultiSolution_Observer::observeSolution(const Epetra_Vector& solution, const std::string& solutionLabel,
00054                Teuchos::RCP<Albany::EigendataStruct> eigenData,
00055                double stamp)
00056 {
00057   if(apps.size() == 0) return;
00058 
00059   int nAppSolns = 1;  // one app solution (maybe more in overloads of observeSolution)
00060   
00061   // Step 1: determine the map for the full solution vector
00062   int nDiscMapCopies = nAppSolns;  
00063   if(eigenData != Teuchos::null) nDiscMapCopies += eigenData->eigenvalueRe->size();
00064 
00065   // Create combined vector map & full solution vector
00066   Teuchos::RCP<const Epetra_Comm> comm = apps[0]->getComm();
00067   Teuchos::RCP<const Epetra_Map> disc_map = apps[0]->getDiscretization()->getMap();
00068   Teuchos::RCP<const Epetra_Map> disc_overlap_map = apps[0]->getDiscretization()->getOverlapMap();
00069   Teuchos::RCP<Epetra_Map> combinedMap = QCAD::CreateCombinedMap(disc_map, nDiscMapCopies, 0, comm);
00070   
00071   Teuchos::RCP<Epetra_Vector> fullSoln = Teuchos::rcp(new Epetra_Vector(*combinedMap));
00072   Teuchos::RCP<Epetra_MultiVector> parts; 
00073   Teuchos::RCP<Epetra_Vector> dummy;
00074   
00075   // Separate full solution vector and fill in parts individually
00076   QCAD::separateCombinedVector(disc_map, nDiscMapCopies, 0, comm, fullSoln, parts, dummy);
00077 
00078     // Trivial Exporter: non-overlapped to non-overlapped data (just copies)
00079   Teuchos::RCP<Epetra_Export> trivial_exporter = Teuchos::rcp(new Epetra_Export(*disc_map, *disc_map));
00080   (*parts)(0)->Export( solution, *trivial_exporter, Insert); // assume solution vector is non-overlapped
00081 
00082     // Overlap Exporter: overlapped to non-overlapped data 
00083   Teuchos::RCP<Epetra_Export> overlap_exporter = Teuchos::rcp(new Epetra_Export(*disc_overlap_map, *disc_map));
00084   
00085   int nEigenvals;
00086   if(eigenData != Teuchos::null) { // transfer real parts of eigenvectors (note: they're stored in overlapped distribution)
00087     nEigenvals = eigenData->eigenvalueRe->size();
00088     for(int k=0; k < nEigenvals; k++) 
00089       (*parts)(nAppSolns+k)->Export( *((*(eigenData->eigenvectorRe))(k)), *overlap_exporter, Insert);
00090   }
00091   else nEigenvals = 0;
00092 
00093 
00094 
00095   //Build a new discretization object that expects combined_map solution vectors and
00096   // includes space for all app states.
00097 
00098   std::vector<std::string> solnVecComps( 2*nDiscMapCopies );  
00099   solnVecComps[0] = solutionLabel; solnVecComps[1] = "S";
00100   for(int i=0; i<nEigenvals; i++) {
00101     std::ostringstream ss1; ss1 << "Eigenvector" << i;
00102     solnVecComps[ 2*(i+nAppSolns) ] = ss1.str(); 
00103     solnVecComps[ 2*(i+nAppSolns)+1 ] = "S";
00104   }
00105 
00106   Teuchos::ParameterList& discList = rootParams->sublist("Discretization", true);
00107   discList.set("Solution Vector Components", Teuchos::Array<std::string>(solnVecComps));
00108   discList.set("Interleaved Ordering", false); //combined vector is concatenated, not "interleaved"
00109 
00110     // Create discretization factory
00111   Albany::DiscretizationFactory discFactory(rootParams, comm);
00112 
00113     // Get mesh specification object: worksetSize, cell topology, etc
00114   Teuchos::ArrayRCP<Teuchos::RCP<Albany::MeshSpecsStruct> > meshSpecs =
00115     discFactory.createMeshSpecs();
00116 
00117   Albany::AbstractFieldContainer::FieldContainerRequirements requirements; //empty
00118   Teuchos::RCP<Albany::StateInfoStruct> stateInfo = apps[0]->getStateMgr().getStateInfoStruct(); //just use apps[0]'s states for now
00119 
00120     //Create a discretization object based on the one in apps[0]
00121   int neq = nDiscMapCopies;
00122   Teuchos::RCP<Piro::MLRigidBodyModes> rigidBodyModes(Teuchos::rcp(new Piro::MLRigidBodyModes(neq)));
00123   Teuchos::RCP<Albany::AbstractDiscretization> my_disc = discFactory.createDiscretization(neq, stateInfo,requirements,rigidBodyModes);  
00124 
00125     //Copy in states from apps (just apps[0] for now)
00126   Albany::StateArrays& my_states = my_disc->getStateArrays();
00127   Albany::StateArrays& appStates = apps[0]->getDiscretization()->getStateArrays();
00128   Teuchos::RCP<Albany::StateInfoStruct> appStateInfo = apps[0]->getStateMgr().getStateInfoStruct();
00129   QCAD::CopyAllStates(appStates, my_states, appStateInfo);
00130 
00131     //Finally, write out the solution using our the created discretization object
00132   my_disc->writeSolution(*fullSoln, stamp, /*overlapped =*/ false);
00133 }
00134 
00135 
00136 
00137 /*void observeSolution(
00138        const Epetra_Vector& solution, double time_or_param_val)
00139 {
00140   Teuchos::RCP<const Epetra_Vector> soln_poisson, soln_eigenvals_dist;
00141   Teuchos::RCP<const Epetra_MultiVector> soln_schrodinger;
00142 
00143   psModel_->separateCombinedVector(Teuchos::rcp(&solution, false), 
00144            soln_poisson, soln_schrodinger, soln_eigenvals_dist);
00145 
00146   int nEigenvals = soln_eigenvals_dist->Map().NumGlobalElements();
00147   Teuchos::RCP<Albany::Application> poisson_app = psModel_->getPoissonApp();      
00148   Teuchos::RCP<Albany::Application> schrodinger_app = psModel_->getSchrodingerApp();      
00149 
00150   // Evaluate state field managers
00151   poisson_app->evaluateStateFieldManager(time_or_param_val, NULL, *soln_poisson);
00152   for(int i=0; i<nEigenvals; i++)
00153     schrodinger_app->evaluateStateFieldManager(time_or_param_val, NULL, *((*soln_schrodinger)(i)) );
00154 
00155   // This must come at the end since it renames the New state 
00156   // as the Old state in preparation for the next step
00157   poisson_app->getStateMgr().updateStates();
00158   schrodinger_app->getStateMgr().updateStates();
00159 
00160   Epetra_Vector *poisson_ovlp_solution = poisson_app->getAdaptSolMgr()->getOverlapSolution(*soln_poisson);
00161   poisson_app->getDiscretization()->writeSolution(*poisson_ovlp_solution, time_or_param_val, true); // soln is overlapped
00162 
00163   for(int i=0; i<nEigenvals; i++) {
00164     Epetra_Vector *schrodinger_ovlp_solution = schrodinger_app->getAdaptSolMgr()->getOverlapSolution(*((*soln_schrodinger)(i)));
00165     schrodinger_app->getDiscretization()->writeSolution(*schrodinger_ovlp_solution, time_or_param_val + i*0.1, true); // soln is overlapped
00166   }
00167 
00168   soln_eigenvals_dist->Print(std::cout << "Coupled PS Solution Eigenvalues:" << std::endl);
00169 
00170   // States: copy states from Poission app's discretization object into psModel's object before writing solution
00171   Albany::StateArrays& psDiscStates = psModel_->getDiscretization()->getStateArrays();
00172   Albany::StateArrays& psPoissonStates = poisson_app->getDiscretization()->getStateArrays();
00173   Teuchos::RCP<Albany::StateInfoStruct> stateInfo = poisson_app->getStateMgr().getStateInfoStruct();
00174   CopyAllStates(psPoissonStates, psDiscStates, stateInfo);
00175 
00176   
00177   //Test: use discretization built by coupled poisson-schrodinger model, which has separated solution vector specified in input file
00178   psModel_->getDiscretization()->writeSolution(solution, time_or_param_val, false); // soln is non-overlapped
00179 }
00180 */
00181 
00182 
00183 
00185 //    Utility functions
00187 
00188 
00189 //Note: assumes dest contains all the allocated states of src
00190 void QCAD::CopyAllStates(Albany::StateArrays& state_arrays,
00191        Albany::StateArrays& dest_arrays,
00192        const Teuchos::RCP<const Albany::StateInfoStruct>& stateInfo)
00193 {
00194   Albany::StateArrayVec& src = state_arrays.elemStateArrays;
00195   Albany::StateArrayVec& dest = dest_arrays.elemStateArrays;
00196   int numWorksets = src.size();
00197   int totalSize;
00198 
00199   for(std::size_t st=0; st < stateInfo->size(); st++) {
00200     const Teuchos::RCP<Albany::StateStruct>& ss = (*stateInfo)[st];
00201     std::string stateNameToCopy = ss->name;
00202     //TODO: check ss to make sure this is a scalar field that copies correctly below
00203     
00204     for (int ws = 0; ws < numWorksets; ws++) {
00205       totalSize = src[ws][stateNameToCopy].size();
00206       for(int i=0; i<totalSize; ++i)
00207   dest[ws][stateNameToCopy][i] = src[ws][stateNameToCopy][i];
00208     }
00209   }
00210 }
00211 
00212 Teuchos::RCP<Epetra_Map> QCAD::CreateCombinedMap(Teuchos::RCP<const Epetra_Map> disc_map,
00213              int numCopiesOfDiscMap, int numAdditionalElements,
00214              const Teuchos::RCP<const Epetra_Comm>& comm)
00215 {
00216   //  Create a map which is the product of <nCopiesOfDiscMap> disc_maps + numAdditionalElements extra elements
00217   //  in such a way that the elements for each disc_map are contiguous in index space (so that we can easily get
00218   //  Epetra vector views to them separately)
00219 
00220   int myRank = comm->MyPID();
00221   int nProcs = comm->NumProc();
00222   int nExtra = numAdditionalElements % nProcs;
00223 
00224   int my_nAdditional = (numAdditionalElements / nProcs) + ((myRank < nExtra) ? 1 : 0);
00225   int my_scalar_offset = myRank * (numAdditionalElements / nProcs) + (myRank < nExtra) ? myRank : nExtra;
00226   int my_nElements = disc_map->NumMyElements() * numCopiesOfDiscMap + my_nAdditional;
00227   std::vector<int> my_global_elements(my_nElements);  //global element indices for this processor
00228 
00229   int disc_nGlobalElements = disc_map->NumGlobalElements();
00230   int disc_nMyElements = disc_map->NumMyElements();
00231   std::vector<int> disc_global_elements(disc_nMyElements);
00232   disc_map->MyGlobalElements(&disc_global_elements[0]);
00233   
00234   for(int k=0; k<numCopiesOfDiscMap; k++) {
00235     for(int l=0; l<disc_nMyElements; l++) {
00236       my_global_elements[k*disc_nMyElements + l] = k*disc_nGlobalElements + disc_global_elements[l];
00237     }
00238   }
00239 
00240   for(int l=0; l < my_nAdditional; l++) {
00241     my_global_elements[numCopiesOfDiscMap*disc_nMyElements + l] = numCopiesOfDiscMap*disc_nGlobalElements + my_scalar_offset + l;
00242   }
00243   
00244   int global_nElements = numCopiesOfDiscMap*disc_nGlobalElements + numAdditionalElements;
00245   return Teuchos::rcp(new Epetra_Map(global_nElements, my_nElements, &my_global_elements[0], 0, *comm));
00246 }
00247 
00248 
00249 void QCAD::separateCombinedVector(Teuchos::RCP<const Epetra_Map> disc_map,
00250           int numCopiesOfDiscMap, int numAdditionalElements,
00251           const Teuchos::RCP<const Epetra_Comm>& comm,
00252           const Teuchos::RCP<Epetra_Vector>& combinedVector,
00253           Teuchos::RCP<Epetra_MultiVector>& disc_parts,
00254           Teuchos::RCP<Epetra_Vector>& additional_part)
00255 {
00256   double* data;
00257   int disc_nMyElements = disc_map->NumMyElements();
00258   int my_nAdditionalEls = combinedVector->Map().NumMyElements() - disc_nMyElements * numCopiesOfDiscMap;
00259   Epetra_Map dist_additionalEl_map(numAdditionalElements, my_nAdditionalEls, 0, *comm);
00260 
00261   if(combinedVector->ExtractView(&data) != 0)
00262     TEUCHOS_TEST_FOR_EXCEPTION(true, Teuchos::Exceptions::InvalidParameter,
00263              "Error!  QCAD::separateCombinedVector cannot extract vector views");
00264 
00265   disc_parts = Teuchos::rcp(new Epetra_MultiVector(::View, *disc_map, &data[0], disc_nMyElements, numCopiesOfDiscMap));
00266   additional_part = Teuchos::rcp(new Epetra_Vector(::View, dist_additionalEl_map, &data[numCopiesOfDiscMap*disc_nMyElements]));
00267   return;
00268 }

Generated on Wed Mar 26 2014 18:36:43 for Albany: a Trilinos-based PDE code by  doxygen 1.7.1