00001
00002
00003
00004
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
00017 #include "Albany_DiscretizationFactory.hpp"
00018 #include "Albany_StateInfoStruct.hpp"
00019 #include "Albany_AbstractFieldContainer.hpp"
00020 #include "Piro_NullSpaceUtils.hpp"
00021
00022
00023
00025
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"));
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"));
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;
00060
00061
00062 int nDiscMapCopies = nAppSolns;
00063 if(eigenData != Teuchos::null) nDiscMapCopies += eigenData->eigenvalueRe->size();
00064
00065
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
00076 QCAD::separateCombinedVector(disc_map, nDiscMapCopies, 0, comm, fullSoln, parts, dummy);
00077
00078
00079 Teuchos::RCP<Epetra_Export> trivial_exporter = Teuchos::rcp(new Epetra_Export(*disc_map, *disc_map));
00080 (*parts)(0)->Export( solution, *trivial_exporter, Insert);
00081
00082
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) {
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
00096
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);
00109
00110
00111 Albany::DiscretizationFactory discFactory(rootParams, comm);
00112
00113
00114 Teuchos::ArrayRCP<Teuchos::RCP<Albany::MeshSpecsStruct> > meshSpecs =
00115 discFactory.createMeshSpecs();
00116
00117 Albany::AbstractFieldContainer::FieldContainerRequirements requirements;
00118 Teuchos::RCP<Albany::StateInfoStruct> stateInfo = apps[0]->getStateMgr().getStateInfoStruct();
00119
00120
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
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
00132 my_disc->writeSolution(*fullSoln, stamp, false);
00133 }
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00185
00187
00188
00189
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
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
00217
00218
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);
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 }