00001
00002
00003
00004
00005
00006
00007 #include "QCAD_Solver.hpp"
00008 #include "QCAD_CoupledPoissonSchrodinger.hpp"
00009 #include "Piro_Epetra_LOCASolver.hpp"
00010 #include "Stokhos.hpp"
00011 #include "Stokhos_Epetra.hpp"
00012 #include "Sacado_PCE_OrthogPoly.hpp"
00013 #include "Teuchos_XMLParameterListHelpers.hpp"
00014
00015
00016
00017
00018
00019
00020 #include "Teuchos_ParameterList.hpp"
00021
00022 #include "Albany_Utils.hpp"
00023 #include "Albany_SolverFactory.hpp"
00024 #include "Albany_StateInfoStruct.hpp"
00025 #include "Albany_EigendataInfoStruct.hpp"
00026
00027 #ifdef ALBANY_CI
00028 #include "AnasaziConfigDefs.hpp"
00029 #include "AnasaziBasicEigenproblem.hpp"
00030 #include "AnasaziBlockDavidsonSolMgr.hpp"
00031 #include "AnasaziBasicOutputManager.hpp"
00032 #endif
00033
00034
00035
00036 namespace QCAD {
00037
00038 void SolveModel(const SolverSubSolver& ss);
00039 void SolveModel(const SolverSubSolver& ss,
00040 Albany::StateArrays*& pInitialStates, Albany::StateArrays*& pFinalStates);
00041 void SolveModel(const QCAD::SolverSubSolver& ss,
00042 Teuchos::RCP<Albany::EigendataStruct>& pInitialEData,
00043 Teuchos::RCP<Albany::EigendataStruct>& pFinalEData);
00044 void SolveModel(const SolverSubSolver& ss,
00045 Albany::StateArrays*& pInitialStates, Albany::StateArrays*& pFinalStates,
00046 Teuchos::RCP<Albany::EigendataStruct>& pInitialEData,
00047 Teuchos::RCP<Albany::EigendataStruct>& pFinalEData);
00048
00049
00050
00051 void CopyStateToContainer(Albany::StateArrays& src,
00052 std::string stateNameToCopy,
00053 std::vector<Intrepid::FieldContainer<RealType> >& dest);
00054 void CopyContainerToState(std::vector<Intrepid::FieldContainer<RealType> >& src,
00055 Albany::StateArrays& dest,
00056 std::string stateNameOfCopy);
00057 void CopyContainer(std::vector<Intrepid::FieldContainer<RealType> >& src,
00058 std::vector<Intrepid::FieldContainer<RealType> >& dest);
00059 void AddContainerToContainer(std::vector<Intrepid::FieldContainer<RealType> >& src,
00060 std::vector<Intrepid::FieldContainer<RealType> >& dest,
00061 double srcFactor, double thisFactor);
00062 void AddContainerToState(std::vector<Intrepid::FieldContainer<RealType> >& src,
00063 Albany::StateArrays& dest,
00064 std::string stateName, double srcFactor, double thisFactor);
00065
00066
00067 void CopyState(Albany::StateArrays& src, Albany::StateArrays& dest, std::string stateNameToCopy);
00068 void AddStateToState(Albany::StateArrays& src, std::string srcStateNameToAdd,
00069 Albany::StateArrays& dest, std::string destStateNameToAddTo);
00070 void SubtractStateFromState(Albany::StateArrays& src, std::string srcStateNameToSubtract,
00071 Albany::StateArrays& dest, std::string destStateNameToSubtractFrom);
00072
00073 double getMaxDifference(Albany::StateArrays& states,
00074 std::vector<Intrepid::FieldContainer<RealType> >& prevState,
00075 std::string stateName);
00076
00077 double getNorm2Difference(Albany::StateArrays& states,
00078 std::vector<Intrepid::FieldContainer<RealType> >& prevState,
00079 std::string stateName);
00080 double getNorm2(std::vector<Intrepid::FieldContainer<RealType> >& container, const Teuchos::RCP<const Epetra_Comm>& comm);
00081 int getElementCount(std::vector<Intrepid::FieldContainer<RealType> >& container);
00082
00083 void ResetEigensolverShift(const Teuchos::RCP<EpetraExt::ModelEvaluator>& Solver, double newShift,
00084 Teuchos::RCP<Teuchos::ParameterList>& eigList);
00085 double GetEigensolverShift(const SolverSubSolver& ss, double pcBelowMinPotential);
00086 void SetPreviousDensityMixing(const Teuchos::RCP<EpetraExt::ModelEvaluator::InArgs> inArgs, double mixingFactor);
00087
00088
00089
00090 std::vector<std::string> string_split(const std::string& s, char delim, bool bProtect=false);
00091 std::string string_remove_whitespace(const std::string& s);
00092 std::vector<std::string> string_parse_function(const std::string& s);
00093 std::map<std::string,std::string> string_parse_arrayref(const std::string& s);
00094 std::vector<int> string_expand_compoundindex(const std::string& indexStr, int min_index, int max_index);
00095
00096 }
00097
00098
00099
00100 QCAD::Solver::
00101 Solver(const Teuchos::RCP<Teuchos::ParameterList>& appParams,
00102 const Teuchos::RCP<const Epetra_Comm>& comm,
00103 const Teuchos::RCP<const Epetra_Vector>& initial_guess) :
00104 maxIter(0),ps_converge_tol(1e-6)
00105 {
00106 using std::string;
00107
00108 solverComm = comm;
00109 mainAppParams = appParams;
00110
00111
00112 Teuchos::ParameterList& problemParams = appParams->sublist("Problem");
00113
00114
00115 problemParams.validateParameters(*getValidProblemParameters(),0);
00116
00117 string problemName, problemDimStr;
00118 problemName = problemParams.get<string>("Name");
00119 problemNameBase = problemName.substr( 0, problemName.length()-3 );
00120 problemDimStr = problemName.substr( problemName.length()-2 );
00121
00122 if(problemDimStr == "1D") numDims = 1;
00123 else if(problemDimStr == "2D") numDims = 2;
00124 else if(problemDimStr == "3D") numDims = 3;
00125 else TEUCHOS_TEST_FOR_EXCEPTION (true, Teuchos::Exceptions::InvalidParameter, std::endl
00126 << "Error! Cannot extract dimension from problem name: "
00127 << problemName << std::endl);
00128
00129 if( !(problemNameBase == "Poisson" || problemNameBase == "Schrodinger" || problemNameBase == "Schrodinger CI" ||
00130 problemNameBase == "Poisson Schrodinger" || problemNameBase == "Poisson Schrodinger CI"))
00131 TEUCHOS_TEST_FOR_EXCEPTION (true, Teuchos::Exceptions::InvalidParameter, std::endl
00132 << "Error! Invalid problem base name: "
00133 << problemNameBase << std::endl);
00134
00135
00136
00137 bVerbose = (comm->MyPID() == 0) && problemParams.get<bool>("Verbose Output", false);
00138
00139 eigensolverName = problemParams.get<string>("Schrodinger Eigensolver","LOBPCG");
00140 bRealEvecs = problemParams.get<bool>("Eigenvectors are Real",false);
00141
00142
00143 if(problemNameBase == "Poisson Schrodinger" || problemNameBase == "Poisson Schrodinger CI") {
00144 bUseIntegratedPS = problemParams.get<bool>("Use Integrated Poisson Schrodinger",true);
00145 maxIter = problemParams.get<int>("Maximum PS Iterations", 100);
00146 shiftPercentBelowMin = problemParams.get<double>("Eigensolver Percent Shift Below Potential Min", 1.0);
00147 ps_converge_tol = problemParams.get<double>("Iterative PS Convergence Tolerance", 1e-6);
00148 fixedPSOcc = problemParams.get<double>("Iterative PS Fixed Occupation", -1.0);
00149 }
00150
00151
00152 if(problemNameBase == "Poisson Schrodinger CI") {
00153 minCIParticles = problemParams.get<int>("Minimum CI Particles",0);
00154 maxCIParticles = problemParams.get<int>("Maximum CI Particles",10);
00155 bUseTotalSpinSymmetry = problemParams.get<bool>("Use S2 Symmetry in CI", false);
00156 }
00157
00158
00159 if(problemNameBase == "Schrodinger CI") {
00160 nCIParticles = problemParams.get<int>("CI Particles");
00161 nCIExcitations = problemParams.get<int>("CI Excitations");
00162 assert(nCIParticles >= nCIExcitations);
00163 }
00164
00165
00166 nEigenvectors = 0;
00167 if(problemNameBase != "Poisson") {
00168 nEigenvectors = problemParams.get<int>("Number of Eigenvalues");
00169 }
00170
00171
00172 std::string piroFilename = problemParams.get<std::string>("Piro Defaults Filename", "");
00173 if(piroFilename.length() > 0) {
00174 const Albany_MPI_Comm mpiComm = Albany::getMpiCommFromEpetraComm(*comm);
00175 Teuchos::RCP<Teuchos::Comm<int> > tcomm = Albany::createTeuchosCommFromMpiComm(mpiComm);
00176 Teuchos::RCP<Teuchos::ParameterList> defaultPiroParams = Teuchos::createParameterList("Default Piro Parameters");
00177 Teuchos::updateParametersFromXmlFileAndBroadcast(piroFilename, defaultPiroParams.ptr(), *tcomm);
00178 Teuchos::ParameterList& piroList = appParams->sublist("Piro", false);
00179 piroList.setParametersNotAlreadySet(*defaultPiroParams);
00180 }
00181
00182
00183 Teuchos::ParameterList& debugParams = appParams->sublist("Debug Output");
00184 std::string debug_initpoissonXML = debugParams.get<std::string>("Initial Poisson XML Input","");
00185 std::string debug_poissonXML = debugParams.get<std::string>("Poisson XML Input","");
00186 std::string debug_schroXML = debugParams.get<std::string>("Schrodinger XML Input","");
00187 std::string debug_psXML = debugParams.get<std::string>("Poisson-Schrodinger XML Input","");
00188 std::string debug_ciXML = debugParams.get<std::string>("Poisson-CI XML Input","");
00189 std::string debug_nochargeXML = debugParams.get<std::string>("CI No Charge XML Input","");
00190 std::string debug_deltaXML = debugParams.get<std::string>("CI Delta XML Input","");
00191 std::string debug_coulombXML = debugParams.get<std::string>("CI Coulomb XML Input","");
00192 std::string debug_coulombImXML = debugParams.get<std::string>("CI Coulomb Imaginary XML Input","");
00193
00194 std::string debug_initpoissonExo = debugParams.get<std::string>("Initial Poisson Exodus Output","");
00195 std::string debug_poissonExo = debugParams.get<std::string>("Poisson Exodus Output","");
00196 std::string debug_schroExo = debugParams.get<std::string>("Schrodinger Exodus Output","");
00197 std::string debug_ciExo = debugParams.get<std::string>("Poisson-CI Exodus Output","");
00198 std::string debug_nochargeExo = debugParams.get<std::string>("CI No Charge Exodus Output","");
00199 std::string debug_deltaExo = debugParams.get<std::string>("CI Delta Exodus Output","");
00200 std::string debug_coulombExo = debugParams.get<std::string>("CI Coulomb Exodus Output","");
00201 std::string debug_coulombImExo = debugParams.get<std::string>("CI Coulomb Imaginary Exodus Output","");
00202
00203
00204
00205 std::string outputExo = appParams->sublist("Discretization").get<std::string>("Exodus Output File Name");
00206
00207
00208 if( problemNameBase == "Poisson" ) {
00209 subProblemAppParams["Poisson"] = createPoissonInputFile(appParams, numDims, nEigenvectors, "none",
00210 debug_poissonXML, outputExo);
00211 defaultSubSolver = "Poisson";
00212 }
00213
00214 else if( problemNameBase == "Schrodinger" ) {
00215 subProblemAppParams["Schrodinger"] = createSchrodingerInputFile(appParams, numDims, nEigenvectors, "none",
00216 debug_schroXML, debug_schroExo);
00217 defaultSubSolver = "Schrodinger";
00218 }
00219
00220 else if( problemNameBase == "Poisson Schrodinger" ) {
00221 subProblemAppParams["InitPoisson"] = createPoissonInputFile(appParams, numDims, nEigenvectors, "initial poisson",
00222 debug_initpoissonXML, debug_initpoissonExo);
00223 subProblemAppParams["Poisson"] = createPoissonInputFile(appParams, numDims, nEigenvectors, "couple to schrodinger",
00224 debug_poissonXML, debug_poissonExo);
00225 subProblemAppParams["Schrodinger"] = createSchrodingerInputFile(appParams, numDims, nEigenvectors, "couple to poisson",
00226 debug_schroXML, debug_schroExo);
00227 if(bUseIntegratedPS) {
00228 subProblemAppParams["PoissonSchrodinger"] = createPoissonSchrodingerInputFile(appParams, numDims, nEigenvectors,
00229 debug_psXML, outputExo);
00230 defaultSubSolver = "PoissonSchrodinger";
00231 }
00232 else defaultSubSolver = "Poisson";
00233 }
00234
00235 else if( problemNameBase == "Schrodinger CI" ) {
00236 subProblemAppParams["CoulombPoisson"] = createPoissonInputFile(appParams, numDims, nEigenvectors, "Coulomb",
00237 debug_coulombXML, debug_coulombExo);
00238 if(!bRealEvecs)
00239 subProblemAppParams["CoulombPoissonIm"] = createPoissonInputFile(appParams, numDims, nEigenvectors, "Coulomb imaginary",
00240 debug_coulombImXML, debug_coulombImExo);
00241 subProblemAppParams["Schrodinger"] = createSchrodingerInputFile(appParams, numDims, nEigenvectors, "none",
00242 debug_schroXML, debug_schroExo);
00243 defaultSubSolver = "Schrodinger";
00244 }
00245
00246 else if( problemNameBase == "Poisson Schrodinger CI" ) {
00247 bUseIntegratedPS = false;
00248
00249 subProblemAppParams["InitPoisson"] = createPoissonInputFile(appParams, numDims, nEigenvectors, "initial poisson",
00250 debug_initpoissonXML, debug_initpoissonExo);
00251 subProblemAppParams["Poisson"] = createPoissonInputFile(appParams, numDims, nEigenvectors, "couple to schrodinger",
00252 debug_poissonXML, debug_poissonExo);
00253 subProblemAppParams["Schrodinger"] = createSchrodingerInputFile(appParams, numDims, nEigenvectors, "couple to poisson",
00254 debug_schroXML, debug_schroExo);
00255 subProblemAppParams["CIPoisson"] = createPoissonInputFile(appParams, numDims, nEigenvectors, "CI", debug_ciXML, debug_ciExo);
00256
00257 if(bUseIntegratedPS)
00258 subProblemAppParams["PoissonSchrodinger"] = createPoissonSchrodingerInputFile(appParams, numDims, nEigenvectors,
00259 debug_psXML, outputExo);
00260 defaultSubSolver = "CIPoisson";
00261
00262
00263 subProblemAppParams["CoulombPoisson"] = createPoissonInputFile(appParams, numDims, nEigenvectors, "Coulomb",
00264 debug_coulombXML, debug_coulombExo);
00265 if(!bRealEvecs)
00266 subProblemAppParams["CoulombPoissonIm"] = createPoissonInputFile(appParams, numDims, nEigenvectors, "Coulomb imaginary",
00267 debug_coulombImXML, debug_coulombImExo);
00268 subProblemAppParams["NoChargePoisson"] = createPoissonInputFile(appParams, numDims, nEigenvectors, "no charge",
00269 debug_nochargeXML, debug_nochargeExo);
00270 subProblemAppParams["DeltaPoisson"] = createPoissonInputFile(appParams, numDims, nEigenvectors, "delta",
00271 debug_deltaXML, debug_deltaExo);
00272 }
00273
00274 else TEUCHOS_TEST_FOR_EXCEPTION(true, Teuchos::Exceptions::InvalidParameter,
00275 std::endl << "Error in QCAD::Solver constructor: " <<
00276 "Invalid problem name base: " << problemNameBase << std::endl);
00277
00278
00279 saved_initial_guess = initial_guess;
00280
00281
00282
00283 std::map<std::string, SolverSubSolverData> subSolversData;
00284 std::map<std::string, Teuchos::RCP<Teuchos::ParameterList> >::const_iterator itp;
00285 for(itp = subProblemAppParams.begin(); itp != subProblemAppParams.end(); ++itp) {
00286 const std::string& name = itp->first;
00287 const Teuchos::RCP<Teuchos::ParameterList>& param_list = itp->second;
00288 const SolverSubSolver& sub = CreateSubSolver( param_list , *comm);
00289
00290 subSolversData[ name ] = CreateSubSolverData( sub );
00291
00292
00293
00294 if(itp == subProblemAppParams.begin()) {
00295 Teuchos::RCP<const Epetra_Map> sub_x_map = sub.app->getMap();
00296 TEUCHOS_TEST_FOR_EXCEPT( sub_x_map == Teuchos::null );
00297 epetra_x_map = Teuchos::rcp(new Epetra_Map( *sub_x_map ));
00298 }
00299 }
00300
00301
00302 bSupportDpDg = true;
00303 std::map<std::string, SolverSubSolverData>::const_iterator it;
00304 for(it = subSolversData.begin(); it != subSolversData.end(); ++it) {
00305 deriv_support = (it->second).deriv_support;
00306 if(deriv_support.none()) { bSupportDpDg = false; break; }
00307 }
00308
00309
00310 if(bSupportDpDg) deriv_support.plus(DERIV_LINEAR_OP);
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323 Teuchos::ParameterList& paramList = problemParams.sublist("Parameters");
00324 setupParameterMapping(paramList, defaultSubSolver, subSolversData);
00325
00326 Teuchos::ParameterList& responseList = problemParams.sublist("Response Functions");
00327 setupResponseMapping(responseList, defaultSubSolver, nEigenvectors, subSolversData);
00328
00329 num_p = (nParameters > 0) ? 1 : 0;
00330 num_g = (responseFns.size() > 0) ? 1 : 0;
00331
00332
00333 #ifndef EPETRA_NO_32BIT_GLOBAL_INDICES
00334 typedef int GlobalIndex;
00335 #else
00336 typedef long long GlobalIndex;
00337 #endif
00338
00339
00340 epetra_param_map = Teuchos::rcp(new Epetra_LocalMap(static_cast<GlobalIndex>(nParameters), 0, *comm));
00341
00342
00343 epetra_response_map = Teuchos::rcp(new Epetra_LocalMap(static_cast<GlobalIndex>(nResponseDoubles), 0, *comm));
00344
00345
00346
00347 epetra_param_vec = Teuchos::rcp(new Epetra_Vector(*(epetra_param_map)));
00348
00349
00350
00351 for(std::size_t i=0; i<nParameters; i++) {
00352 (*epetra_param_vec)[i] = paramFnVecs[i][0]->getInitialParam(subSolversData);
00353 }
00354 }
00355
00356 QCAD::Solver::~Solver()
00357 {
00358 }
00359
00360
00361 Teuchos::RCP<Teuchos::ParameterList>
00362 QCAD::Solver::createPoissonInputFile(const Teuchos::RCP<Teuchos::ParameterList>& appParams,
00363 int numDims, int nEigen, const std::string& specialProcessing,
00364 const std::string& xmlOutputFile, const std::string& exoOutputFile) const
00365 {
00366 Teuchos::ParameterList& problemParams = appParams->sublist("Problem");
00367
00368 int vizDetail = problemParams.get<int>("Phalanx Graph Visualization Detail",0);
00369 double lenUnit = problemParams.get<double>("Length Unit In Meters", 1e-6);
00370 double energyUnit = problemParams.get<double>("Energy Unit In Electron Volts", 1.0);
00371 std::string matrlFile = problemParams.get<std::string>("MaterialDB Filename", "materials.xml");
00372
00373 bool bXCPot = problemParams.get<bool>("Include exchange-correlation potential",false);
00374 bool bQBOnly = problemParams.get<bool>("Only solve schrodinger in quantum blocks",true);
00375 bool bUsePCMethod = problemParams.get<bool>("Use predictor-corrector method",false);
00376
00377
00378 double Temp = -1;
00379 if(specialProcessing == "Coulomb" || specialProcessing == "Coulomb imaginary")
00380 Temp = problemParams.get<double>("Temperature",-1);
00381 else Temp = problemParams.get<double>("Temperature");
00382
00383
00384
00385 Teuchos::ParameterList& poisson_subList = problemParams.sublist("Poisson Problem", false);
00386 Teuchos::ParameterList& schro_subList = problemParams.sublist("Schrodinger Problem", false);
00387
00388
00389 Teuchos::RCP<Teuchos::ParameterList> poisson_appParams =
00390 Teuchos::createParameterList("Poisson Subapplication Parameters - " + specialProcessing);
00391 Teuchos::ParameterList& poisson_probParams = poisson_appParams->sublist("Problem",false);
00392
00393 poisson_probParams.set("Name", QCAD::strdim("Poisson",numDims));
00394 poisson_probParams.set("Phalanx Graph Visualization Detail", vizDetail);
00395 poisson_probParams.set("Length Unit In Meters",lenUnit);
00396 poisson_probParams.set("Energy Unit In Electron Volts",energyUnit);
00397 poisson_probParams.set("MaterialDB Filename", matrlFile);
00398 if(Temp >= 0) poisson_probParams.set("Temperature",Temp);
00399
00400
00401 {
00402 Teuchos::ParameterList auto_sourceList;
00403 auto_sourceList.set("Factor",1.0);
00404 auto_sourceList.set("Device","elementblocks");
00405
00406 if(specialProcessing == "initial poisson") {
00407 auto_sourceList.set("Quantum Region Source", "semiclassical");
00408 auto_sourceList.set("Non Quantum Region Source", "semiclassical");
00409
00410 } else if (specialProcessing == "couple to schrodinger") {
00411 auto_sourceList.set("Quantum Region Source", "schrodinger");
00412 auto_sourceList.set("Non Quantum Region Source", bQBOnly ? "semiclassical" : "schrodinger");
00413 auto_sourceList.set("Eigenvectors to Import", nEigen);
00414 auto_sourceList.set("Eigenvectors are Real", bRealEvecs);
00415 auto_sourceList.set("Use predictor-corrector method", bUsePCMethod);
00416 auto_sourceList.set("Include exchange-correlation potential", bXCPot);
00417 auto_sourceList.set("Fixed Quantum Occupation", fixedPSOcc);
00418
00419 } else if (specialProcessing == "Coulomb") {
00420 auto_sourceList.set("Quantum Region Source", "coulomb");
00421 auto_sourceList.set("Non Quantum Region Source", "none");
00422 auto_sourceList.set("Imaginary Part of Coulomb Source", false);
00423 auto_sourceList.set("Eigenvectors to Import", nEigen);
00424 auto_sourceList.set("Eigenvectors are Real", bRealEvecs);
00425
00426 } else if (specialProcessing == "Coulomb imaginary") {
00427 auto_sourceList.set("Quantum Region Source", "coulomb");
00428 auto_sourceList.set("Non Quantum Region Source", "none");
00429 auto_sourceList.set("Imaginary Part of Coulomb Source", true);
00430 auto_sourceList.set("Eigenvectors to Import", nEigen);
00431 auto_sourceList.set("Eigenvectors are Real", bRealEvecs);
00432
00433 } else if (specialProcessing == "delta") {
00434 auto_sourceList.set("Quantum Region Source", "schrodinger");
00435 auto_sourceList.set("Non Quantum Region Source", "none");
00436 auto_sourceList.set("Eigenvectors to Import", nEigen);
00437 auto_sourceList.set("Eigenvectors are Real", bRealEvecs);
00438 auto_sourceList.set("Include exchange-correlation potential", bXCPot);
00439 auto_sourceList.set("Fixed Quantum Occupation", fixedPSOcc);
00440
00441 } else if (specialProcessing == "no charge") {
00442 auto_sourceList.set("Quantum Region Source", "none");
00443 auto_sourceList.set("Non Quantum Region Source", "none");
00444 auto_sourceList.set("Eigenvectors to Import", nEigen);
00445 auto_sourceList.set("Eigenvectors are Real", bRealEvecs);
00446
00447 } else if (specialProcessing == "CI") {
00448 auto_sourceList.set("Quantum Region Source", "ci");
00449 auto_sourceList.set("Non Quantum Region Source", "semiclassical");
00450 auto_sourceList.set("Eigenvectors to Import", nEigen);
00451 auto_sourceList.set("Eigenvectors are Real", bRealEvecs);
00452
00453 } else if (specialProcessing != "none")
00454 TEUCHOS_TEST_FOR_EXCEPTION( true, Teuchos::Exceptions::InvalidParameter,
00455 "Invalid special processing for Poisson input: " << specialProcessing);
00456
00457 Teuchos::ParameterList& sourceList = poisson_probParams.sublist("Poisson Source", false);
00458 if(poisson_subList.isSublist("Poisson Source"))
00459 sourceList.setParameters( poisson_subList.sublist("Poisson Source") );
00460 sourceList.setParametersNotAlreadySet( auto_sourceList );
00461 }
00462
00463
00464 {
00465 Teuchos::ParameterList auto_permList;
00466 auto_permList.set("Permittivity Type","Block Dependent");
00467
00468 Teuchos::ParameterList& permList = poisson_probParams.sublist("Permittivity", false);
00469 if(poisson_subList.isSublist("Permittivity"))
00470 permList.setParameters( poisson_subList.sublist("Permittivity") );
00471 permList.setParametersNotAlreadySet( auto_permList );
00472 }
00473
00474
00475
00476 if(poisson_subList.isSublist("Dirichlet BCs")) {
00477 Teuchos::ParameterList& poisson_dbcList = poisson_probParams.sublist("Dirichlet BCs", false);
00478 poisson_dbcList.setParameters(poisson_subList.sublist("Dirichlet BCs"));
00479 }
00480 else if(schro_subList.isSublist("Dirichlet BCs")) {
00481 Teuchos::ParameterList& poisson_dbcList = poisson_probParams.sublist("Dirichlet BCs", false);
00482 const Teuchos::ParameterList& schro_dbcList = schro_subList.sublist("Dirichlet BCs");
00483 Teuchos::ParameterList::ConstIterator it; double* dummy = NULL;
00484 for(it = schro_dbcList.begin(); it != schro_dbcList.end(); ++it) {
00485 std::string dbcName = schro_dbcList.name(it);
00486 std::size_t k = dbcName.find("psi");
00487 if( k != std::string::npos ) {
00488 dbcName.replace(k, 3 , "Phi");
00489 poisson_dbcList.set( dbcName, schro_dbcList.entry(it).getValue(dummy) );
00490 }
00491 }
00492 }
00493
00494
00495
00496
00497 if( specialProcessing == "Coulomb" || specialProcessing == "Coulomb imaginary" ) {
00499 Teuchos::ParameterList& paramList = poisson_probParams.sublist("Parameters", false);
00500 if(poisson_subList.isSublist("Parameters"))
00501 paramList.setParameters(poisson_subList.sublist("Parameters"));
00502
00503 int nParams = paramList.get<int>("Number", 0);
00504 paramList.set("Number", nParams + 2);
00505 paramList.set(Albany::strint("Parameter",nParams), "Source Eigenvector 1");
00506 paramList.set(Albany::strint("Parameter",nParams+1), "Source Eigenvector 2");
00507 }
00508 else if(specialProcessing == "couple to schrodinger" ) {
00509 Teuchos::ParameterList& paramList = poisson_probParams.sublist("Parameters", false);
00510 if(poisson_subList.isSublist("Parameters"))
00511 paramList.setParameters(poisson_subList.sublist("Parameters"));
00512
00513 int nParams = paramList.get<int>("Number", 0);
00514 paramList.set("Number", nParams + 1);
00515 paramList.set(Albany::strint("Parameter",nParams), "Previous Quantum Density Mixing Factor");
00516 }
00517 else {
00518 Teuchos::ParameterList& poisson_paramsList = poisson_probParams.sublist("Parameters", false);
00519 if(poisson_subList.isSublist("Parameters"))
00520 poisson_paramsList.setParameters(poisson_subList.sublist("Parameters"));
00521 else poisson_paramsList.set("Number", 0);
00522 }
00523
00524
00525
00526 bool addCoulombIntegralResponses = ((specialProcessing == "delta") ||
00527 (specialProcessing == "Coulomb") ||
00528 (specialProcessing == "Coulomb imaginary") ||
00529 (specialProcessing == "no charge") );
00530
00531 if(addCoulombIntegralResponses)
00532 {
00533 Teuchos::ParameterList& responseList = poisson_probParams.sublist("Response Functions", false);
00534 if(poisson_subList.isSublist("Response Functions"))
00535 responseList.setParameters(poisson_subList.sublist("Response Functions"));
00536
00538 int initial_nResponses = responseList.get<int>("Number",0);
00539 int added_nResponses = nEigen * (nEigen + 1) / 2;
00540 if(!bRealEvecs) added_nResponses *= 2;
00541
00542 char buf1[200], buf2[200], buf1i[200], buf2i[200];
00543 responseList.set("Number", initial_nResponses + added_nResponses);
00544
00545
00546 for(int i=initial_nResponses-1; i >= 0; i--) {
00547 std::string respType = responseList.get<std::string>(Albany::strint("Response",i));
00548 responseList.set(Albany::strint("Response",i + added_nResponses), respType);
00549 if(responseList.isSublist( Albany::strint("ResponseParams",i) )) {
00550 responseList.sublist( Albany::strint("ResponseParams",i + added_nResponses) ) =
00551 Teuchos::ParameterList(responseList.sublist( Albany::strint("ResponseParams",i) ) );
00552 responseList.sublist( Albany::strint("ResponseParams",i) ) = Teuchos::ParameterList(Albany::strint("ResponseParams",i));
00553 }
00554 }
00555
00556 int iResponse = 0;
00557 for(int i=0; i<nEigenvectors; i++) {
00558 sprintf(buf1, "%s_Re%d", "Evec", i);
00559 sprintf(buf1i, "%s_Im%d", "Evec", i);
00560 for(int j=i; j<nEigenvectors; j++) {
00561 sprintf(buf2, "%s_Re%d", "Evec", j);
00562 sprintf(buf2i, "%s_Im%d", "Evec", j);
00563
00564 responseList.set(Albany::strint("Response",iResponse), "Field Integral");
00565 Teuchos::ParameterList& responseParams = responseList.sublist(Albany::strint("ResponseParams",iResponse));
00566 responseParams.set("Field Name", "Electric Potential");
00567 responseParams.set("Field Name 1", buf1);
00568 responseParams.set("Field Name 2", buf2);
00569 if(!bRealEvecs) {
00570 responseParams.set("Field Name Im 1", buf1i);
00571 responseParams.set("Field Name Im 2", buf2i);
00572 responseParams.set("Conjugate Field 1", true);
00573 responseParams.set("Conjugate Field 2", false);
00574 }
00575 responseParams.set("Integrand Length Unit", "mesh");
00576 responseParams.set("Return Imaginary Part", false);
00577
00578 iResponse++;
00579
00580 if(!bRealEvecs) {
00581 responseList.set(Albany::strint("Response",iResponse), "Field Integral");
00582 Teuchos::ParameterList& responseParams2 = responseList.sublist(Albany::strint("ResponseParams",iResponse));
00583 responseParams2.set("Field Name", "Electric Potential");
00584 responseParams2.set("Field Name 1", buf1); responseParams2.set("Field Name Im 1", buf1i);
00585 responseParams2.set("Field Name 2", buf2); responseParams2.set("Field Name Im 2", buf2i);
00586 responseParams2.set("Conjugate Field 1", true);
00587 responseParams2.set("Conjugate Field 2", false);
00588 responseParams2.set("Integrand Length Unit", "mesh");
00589 responseParams2.set("Return Imaginary Part", true);
00590
00591 iResponse++;
00592 }
00593
00594 }
00595 }
00596 }
00597 else if(specialProcessing == "couple to schrodinger" || specialProcessing == "initial poisson" || specialProcessing == "CI")
00598 {
00599
00600 Teuchos::ParameterList& responseList = poisson_probParams.sublist("Response Functions", false);
00601 if(poisson_subList.isSublist("Response Functions"))
00602 responseList.setParameters(poisson_subList.sublist("Response Functions"));
00603
00604 int nResponses = responseList.get<int>("Number",0);
00605 int nAddedResponses = 7;
00606 responseList.set("Number", nResponses+nAddedResponses);
00607
00608 int iResponse = nResponses;
00609 Teuchos::ParameterList* pResponseParams;
00610
00611
00612 responseList.set(Albany::strint("Response",iResponse), "Save Field");
00613 pResponseParams = &responseList.sublist(Albany::strint("ResponseParams",iResponse));
00614 pResponseParams->set("Field Name", "Electron Density");
00615 pResponseParams->set("State Name", "PS Saved Electron Density");
00616 pResponseParams->set("Output Cell Average", false);
00617 pResponseParams->set("Output to Exodus", false);
00618 iResponse++;
00619
00620 responseList.set(Albany::strint("Response",iResponse), "Save Field");
00621 pResponseParams = &responseList.sublist(Albany::strint("ResponseParams",iResponse));
00622 pResponseParams->set("Field Name", "Conduction Band");
00623 pResponseParams->set("State Name", "PS Conduction Band");
00624 pResponseParams->set("Output Cell Average", false);
00625 pResponseParams->set("Output to Exodus", false);
00626 iResponse++;
00627
00628 responseList.set(Albany::strint("Response",iResponse), "Save Field");
00629 pResponseParams = &responseList.sublist(Albany::strint("ResponseParams",iResponse));
00630 pResponseParams->set("Field Name", "Potential");
00631 pResponseParams->set("State Name", "PS Saved Solution");
00632 pResponseParams->set("Output Cell Average", false);
00633 pResponseParams->set("Output to Exodus", false);
00634 iResponse++;
00635
00636
00637
00638 responseList.set(Albany::strint("Response",iResponse), "Save Field");
00639 pResponseParams = &responseList.sublist(Albany::strint("ResponseParams",iResponse));
00640 pResponseParams->set("Field Name", "Potential");
00641 pResponseParams->set("State Name", "PS Previous Poisson Potential");
00642 pResponseParams->set("Output Cell Average", false);
00643 pResponseParams->set("Output to Exodus", false);
00644 pResponseParams->set("Memory Placeholder Only", true);
00645 iResponse++;
00646
00647
00648
00649 responseList.set(Albany::strint("Response",iResponse), "Save Field");
00650 pResponseParams = &responseList.sublist(Albany::strint("ResponseParams",iResponse));
00651 pResponseParams->set("Field Name", "Electron Density");
00652 pResponseParams->set("State Name", "PS Previous Electron Density");
00653 pResponseParams->set("Output Cell Average", false);
00654 pResponseParams->set("Output to Exodus", false);
00655 pResponseParams->set("Memory Placeholder Only", true);
00656 iResponse++;
00657
00658
00659
00660 responseList.set(Albany::strint("Response",iResponse), "Field Integral");
00661 pResponseParams = &responseList.sublist(Albany::strint("ResponseParams",iResponse));
00662 pResponseParams->set("Field Name", "Electron Density");
00663 pResponseParams->set("Quantum Element Blocks Only", true);
00664 iResponse++;
00665
00666
00667
00668
00669 responseList.set(Albany::strint("Response",iResponse), "Field Value");
00670 pResponseParams = &responseList.sublist(Albany::strint("ResponseParams",iResponse));
00671 pResponseParams->set("Operation", "Minimize");
00672 pResponseParams->set("Operation Field Name", "Conduction Band");
00673 pResponseParams->set("Quantum Element Blocks Only", true);
00674
00675 }
00676 else {
00677 Teuchos::ParameterList& poisson_respList = poisson_probParams.sublist("Response Functions", false);
00678 if(poisson_subList.isSublist("Response Functions"))
00679 poisson_respList.setParameters(poisson_subList.sublist("Response Functions"));
00680 else poisson_respList.set("Number", 0);
00681 }
00682
00683
00684 if(problemParams.isSublist("Initial Condition"))
00685 {
00686 Teuchos::ParameterList& icList = poisson_probParams.sublist("Initial Condition", false);
00687 icList.setParameters( problemParams.sublist("Initial Condition") );
00688 }
00689
00690
00691
00692 Teuchos::ParameterList& discList = appParams->sublist("Discretization");
00693 Teuchos::ParameterList& poisson_discList = poisson_appParams->sublist("Discretization", false);
00694 poisson_discList.setParameters(discList);
00695 if(exoOutputFile.length() > 0)
00696 poisson_discList.set("Exodus Output File Name",exoOutputFile);
00697 else poisson_discList.remove("Exodus Output File Name",false);
00698
00699
00700 Teuchos::ParameterList& poisson_piroList = poisson_appParams->sublist("Piro", false);
00701 poisson_piroList.setParameters( appParams->sublist("Piro") );
00702
00703 if(specialProcessing != "none")
00704 poisson_piroList.sublist("Analysis").sublist("Solve").set("Compute Sensitivities", false);
00705
00706 if(xmlOutputFile.length() > 0 && solverComm->MyPID() == 0)
00707 Teuchos::writeParameterListToXmlFile(*poisson_appParams, xmlOutputFile);
00708
00709 return poisson_appParams;
00710 }
00711
00712
00713 Teuchos::RCP<Teuchos::ParameterList>
00714 QCAD::Solver::createSchrodingerInputFile(const Teuchos::RCP<Teuchos::ParameterList>& appParams,
00715 int numDims, int nEigen, const std::string& specialProcessing,
00716 const std::string& xmlOutputFile, const std::string& exoOutputFile) const
00717 {
00718 Teuchos::ParameterList& problemParams = appParams->sublist("Problem");
00719
00720 int vizDetail = problemParams.get<int>("Phalanx Graph Visualization Detail",0);
00721 double lenUnit = problemParams.get<double>("Length Unit In Meters", 1e-6);
00722 double energyUnit = problemParams.get<double>("Energy Unit In Electron Volts", 1.0);
00723 std::string matrlFile = problemParams.get<std::string>("MaterialDB Filename", "materials.xml");
00724
00725
00726 bool bQBOnly = problemParams.get<bool>("Only solve schrodinger in quantum blocks",true);
00727
00728
00729 Teuchos::ParameterList& schro_subList = problemParams.sublist("Schrodinger Problem", false);
00730 Teuchos::ParameterList& poisson_subList = problemParams.sublist("Poisson Problem", false);
00731
00732
00733 Teuchos::RCP<Teuchos::ParameterList> schro_appParams =
00734 Teuchos::createParameterList("Schrodinger Subapplication Parameters");
00735 Teuchos::ParameterList& schro_probParams = schro_appParams->sublist("Problem",false);
00736
00737 schro_probParams.set("Name", QCAD::strdim("Schrodinger",numDims));
00738 if(eigensolverName == "LOBPCG")
00739 schro_probParams.set("Solution Method", "Eigensolve");
00740 else if(eigensolverName == "LOCA")
00741 schro_probParams.set("Solution Method", "Continuation");
00742 else
00743 TEUCHOS_TEST_FOR_EXCEPTION( true, Teuchos::Exceptions::InvalidParameter,
00744 "Invalid eigensolver name for Schrodinger input: " << eigensolverName);
00745
00746 schro_probParams.set("Phalanx Graph Visualization Detail", vizDetail);
00747 schro_probParams.set("Energy Unit In Electron Volts",energyUnit);
00748 schro_probParams.set("Length Unit In Meters",lenUnit);
00749 schro_probParams.set("MaterialDB Filename", matrlFile);
00750 schro_probParams.set("Only solve in quantum blocks", bQBOnly);
00751
00752
00753 if(specialProcessing == "couple to poisson")
00754 {
00755 Teuchos::ParameterList auto_potList;
00756 auto_potList.set("Scaling Factor",1.0);
00757 auto_potList.set("Type","From State");
00758 auto_potList.set("State Name", "PS Conduction Band");
00759
00760 Teuchos::ParameterList& potList = schro_probParams.sublist("Potential", false);
00761 if(schro_subList.isSublist("Potential"))
00762 potList.setParameters(schro_subList.sublist("Potential"));
00763 potList.setParametersNotAlreadySet(auto_potList);
00764 }
00765 else if(schro_subList.isSublist("Potential")) {
00766 schro_probParams.sublist("Potential", false).setParameters(schro_subList.sublist("Potential"));
00767 }
00768
00769
00770
00771 if(eigensolverName == "LOCA") {
00772 if(schro_subList.isSublist("Dirichlet BCs")) {
00773 Teuchos::ParameterList& schro_dbcList = schro_probParams.sublist("Dirichlet BCs", false);
00774 schro_dbcList.setParameters(schro_subList.sublist("Dirichlet BCs"));
00775 }
00776 else if(poisson_subList.isSublist("Dirichlet BCs")) {
00777 Teuchos::ParameterList& schro_dbcList = schro_probParams.sublist("Dirichlet BCs", false);
00778 const Teuchos::ParameterList& poisson_dbcList = poisson_subList.sublist("Dirichlet BCs");
00779 Teuchos::ParameterList::ConstIterator it;
00780 for(it = poisson_dbcList.begin(); it != poisson_dbcList.end(); ++it) {
00781 std::string dbcName = poisson_dbcList.name(it);
00782 std::size_t k = dbcName.find("Phi");
00783 if( k != std::string::npos ) {
00784 dbcName.replace(k, 3, "psi");
00785 schro_dbcList.set( dbcName, 0.0 );
00786 }
00787 }
00788 }
00789 }
00790
00791
00792
00793 {
00794 Teuchos::ParameterList& paramsList = schro_probParams.sublist("Parameters", false);
00795 if(schro_subList.isSublist("Parameters"))
00796 paramsList.setParameters(schro_subList.sublist("Parameters"));
00797
00798 bool bAddScalingFactor = true;
00799 Teuchos::ParameterList::ConstIterator it; std::string* dummy = NULL;
00800 for(it = paramsList.begin(); it != paramsList.end(); ++it) {
00801 if(paramsList.entry(it).isType<std::string>() &&
00802 paramsList.entry(it).getValue(dummy) == "Schrodinger Potential Scaling Factor") {
00803 bAddScalingFactor = false; break;
00804 }
00805 }
00806
00807 if(bAddScalingFactor) {
00808 int nParams = paramsList.get<int>("Number",0);
00809 paramsList.set("Number", nParams+1);
00810 paramsList.set( Albany::strint("Parameter",nParams), "Schrodinger Potential Scaling Factor" );
00811 }
00812 }
00813
00814
00815 if(specialProcessing == "couple to poisson")
00816 {
00817
00818 Teuchos::ParameterList& responseList = schro_probParams.sublist("Response Functions", false);
00819 if(schro_subList.isSublist("Response Functions"))
00820 responseList.setParameters(schro_subList.sublist("Response Functions"));
00821
00822 int nResponses = responseList.get<int>("Number",0);
00823 responseList.set("Number", nResponses+3);
00824
00825
00826
00827
00828 responseList.set(Albany::strint("Response",nResponses), "Save Field");
00829 Teuchos::ParameterList& responseParams1 = responseList.sublist(Albany::strint("ResponseParams",nResponses));
00830 responseParams1.set("Field Name", "V");
00831 responseParams1.set("State Name", "PS Conduction Band");
00832 responseParams1.set("Output Cell Average", false);
00833 responseParams1.set("Output to Exodus", false);
00834 responseParams1.set("Memory Placeholder Only", true);
00835
00836
00837
00838 responseList.set(Albany::strint("Response",nResponses+1), "Save Field");
00839 Teuchos::ParameterList& responseParams2 = responseList.sublist(Albany::strint("ResponseParams",nResponses+1));
00840 responseParams2.set("Field Name", "V");
00841 responseParams2.set("State Name", "PS Previous Poisson Potential");
00842 responseParams2.set("Output Cell Average", false);
00843 responseParams2.set("Output to Exodus", false);
00844 responseParams2.set("Memory Placeholder Only", true);
00845
00846
00847
00848
00849 responseList.set(Albany::strint("Response",nResponses+2), "Save Field");
00850 Teuchos::ParameterList& responseParams3 = responseList.sublist(Albany::strint("ResponseParams",nResponses+2));
00851 responseParams3.set("Field Name", "V");
00852 responseParams3.set("State Name", "PS Previous Electron Density");
00853 responseParams3.set("Output Cell Average", false);
00854 responseParams3.set("Output to Exodus", false);
00855 responseParams3.set("Memory Placeholder Only", true);
00856
00857 }
00858 else {
00859 Teuchos::ParameterList& schro_respList = schro_probParams.sublist("Response Functions", false);
00860 if(schro_subList.isSublist("Response Functions"))
00861 schro_respList.setParameters(schro_subList.sublist("Response Functions"));
00862 else schro_respList.set("Number", 0);
00863 }
00864
00865
00866 Teuchos::ParameterList& discList = appParams->sublist("Discretization");
00867 Teuchos::ParameterList& schro_discList = schro_appParams->sublist("Discretization", false);
00868 schro_discList.setParameters(discList);
00869 if(exoOutputFile.length() > 0)
00870 schro_discList.set("Exodus Output File Name",exoOutputFile);
00871 else schro_discList.remove("Exodus Output File Name",false);
00872
00873
00874 Teuchos::ParameterList& schro_piroList = schro_appParams->sublist("Piro", false);
00875 schro_piroList.setParameters( appParams->sublist("Piro") );
00876 schro_piroList.sublist("Analysis").sublist("Solve").set("Compute Sensitivities", false);
00877
00878
00879 schro_piroList.sublist("LOCA").sublist("Stepper").set("Compute Eigenvalues", true);
00880 schro_piroList.sublist("LOCA").sublist("Stepper").sublist("Eigensolver").set("Num Eigenvalues", nEigen);
00881 schro_piroList.sublist("LOCA").sublist("Stepper").sublist("Eigensolver").set("Save Eigenvectors", nEigen);
00882
00883 if(xmlOutputFile.length() > 0 && solverComm->MyPID() == 0)
00884 Teuchos::writeParameterListToXmlFile(*schro_appParams, xmlOutputFile);
00885
00886 return schro_appParams;
00887 }
00888
00889
00890 Teuchos::RCP<Teuchos::ParameterList>
00891 QCAD::Solver::createPoissonSchrodingerInputFile(const Teuchos::RCP<Teuchos::ParameterList>& appParams,
00892 int numDims, int nEigen, const std::string& xmlOutputFile,
00893 const std::string& exoOutputFile) const
00894 {
00895 Teuchos::ParameterList& problemParams = appParams->sublist("Problem");
00896
00897 int vizDetail = problemParams.get<int>("Phalanx Graph Visualization Detail");
00898 double lenUnit = problemParams.get<double>("Length Unit In Meters", 1e-6);
00899 double energyUnit = problemParams.get<double>("Energy Unit In Electron Volts", 1.0);
00900 std::string matrlFile = problemParams.get<std::string>("MaterialDB Filename", "materials.xml");
00901
00902 bool bXCPot = problemParams.get<bool>("Include exchange-correlation potential",false);
00903 bool bQBOnly = problemParams.get<bool>("Only solve schrodinger in quantum blocks",true);
00904
00905 double Temp = problemParams.get<double>("Temperature");
00906
00907
00908 Teuchos::ParameterList& poisson_subList = problemParams.sublist("Poisson Problem", false);
00909 Teuchos::ParameterList& schro_subList = problemParams.sublist("Schrodinger Problem", false);
00910
00911
00912 Teuchos::RCP<Teuchos::ParameterList> ps_appParams =
00913 Teuchos::createParameterList("Poisson-Schrodinger Subapplication Parameters");
00914 Teuchos::ParameterList& ps_probParams = ps_appParams->sublist("Problem",false);
00915
00916 ps_probParams.set("Solution Method", "QCAD Poisson-Schrodinger");
00917 ps_probParams.set("Name", QCAD::strdim("Poisson Schrodinger",numDims));
00918 ps_probParams.set("Phalanx Graph Visualization Detail", vizDetail);
00919 ps_probParams.set("Length Unit In Meters",lenUnit);
00920 ps_probParams.set("Energy Unit In Electron Volts",energyUnit);
00921 ps_probParams.set("MaterialDB Filename", matrlFile);
00922 ps_probParams.set("Temperature",Temp);
00923 ps_probParams.set("Number of Eigenvalues",nEigen);
00924 ps_probParams.set("Verbose Output", true);
00925
00926 ps_probParams.set("Include exchange-correlation potential", bXCPot);
00927 ps_probParams.set("Only solve schrodinger in quantum blocks", bQBOnly);
00928
00929
00930 Teuchos::ParameterList& ps_poissonParams = ps_probParams.sublist("Poisson Problem",false);
00931
00932 if(poisson_subList.isSublist("Poisson Source")) {
00933 Teuchos::ParameterList& tmp = ps_poissonParams.sublist("Poisson Source", false);
00934 tmp.setParameters(poisson_subList.sublist("Poisson Source"));
00935 }
00936
00937 if(poisson_subList.isSublist("Dirichlet BCs")) {
00938 Teuchos::ParameterList& tmp = ps_poissonParams.sublist("Dirichlet BCs", false);
00939 tmp.setParameters(poisson_subList.sublist("Dirichlet BCs"));
00940 }
00941
00942 if(poisson_subList.isSublist("Parameters")) {
00943 Teuchos::ParameterList& tmp = ps_poissonParams.sublist("Parameters", false);
00944 tmp.setParameters(poisson_subList.sublist("Parameters"));
00945 }
00946
00947 if(poisson_subList.isSublist("Response Functions")) {
00948 Teuchos::ParameterList& tmp = ps_poissonParams.sublist("Response Functions", false);
00949 tmp.setParameters(poisson_subList.sublist("Response Functions"));
00950 }
00951
00952
00953
00954 Teuchos::ParameterList& ps_schroParams = ps_probParams.sublist("Schrodinger Problem",false);
00955
00956
00957 if(schro_subList.isSublist("Dirichlet BCs")) {
00958 Teuchos::ParameterList& tmp = ps_schroParams.sublist("Dirichlet BCs", false);
00959 tmp.setParameters(schro_subList.sublist("Dirichlet BCs"));
00960 }
00961
00962 if(schro_subList.isSublist("Parameters")) {
00963 Teuchos::ParameterList& tmp = ps_schroParams.sublist("Parameters", false);
00964 tmp.setParameters(schro_subList.sublist("Parameters"));
00965 }
00966
00967 if(schro_subList.isSublist("Response Functions")) {
00968 Teuchos::ParameterList& tmp = ps_schroParams.sublist("Response Functions", false);
00969 tmp.setParameters(schro_subList.sublist("Response Functions"));
00970 }
00971
00972
00973
00974 if(appParams->isSublist("Debug Output")) {
00975 Teuchos::ParameterList& debugParams = appParams->sublist("Debug Output");
00976 std::string poissonXML = debugParams.get<std::string>("PS Poisson XML Input","");
00977 std::string schroXML = debugParams.get<std::string>("PS Schrodinger XML Input","");
00978 std::string poissonExo = debugParams.get<std::string>("PS Poisson Exodus Output","");
00979 std::string schroExo = debugParams.get<std::string>("PS Schrodinger Exodus Output","");
00980
00981 Teuchos::ParameterList& ps_debugParams = ps_appParams->sublist("Debug Output");
00982 if(poissonXML.length() > 0) ps_debugParams.set("Poisson XML Input", poissonXML);
00983 if(schroXML.length() > 0) ps_debugParams.set("Schrodinger XML Input", schroXML);
00984 if(poissonExo.length() > 0) ps_debugParams.set("Poisson Exodus Output", poissonExo);
00985 if(schroExo.length() > 0) ps_debugParams.set("Schrodinger Exodus Output", schroExo);
00986 }
00987
00988
00989 Teuchos::ParameterList& discList = appParams->sublist("Discretization");
00990 Teuchos::ParameterList& ps_discList = ps_appParams->sublist("Discretization", false);
00991 ps_discList.setParameters(discList);
00992 if(exoOutputFile.length() > 0)
00993 ps_discList.set("Exodus Output File Name",exoOutputFile);
00994 else ps_discList.remove("Exodus Output File Name",false);
00995
00996
00997
00998 Teuchos::ParameterList& ps_piroList = ps_appParams->sublist("Piro", false);
00999 ps_piroList.setParameters( appParams->sublist("Piro") );
01000 ps_piroList.set("Solver Type", "NOX");
01001
01002
01003
01004
01005 Teuchos::ParameterList& ps_backtrackList = ps_piroList.sublist("NOX").sublist("Line Search").sublist("Backtrack");
01006 const Teuchos::ParameterList& backtrackList =
01007 appParams->sublist("Piro").sublist("NOX").sublist("Line Search").sublist("Backtrack");
01008
01009 if(backtrackList.isType<double>("CPS Default Step"))
01010 ps_backtrackList.set("Default Step", backtrackList.get<double>("CPS Default Step"));
01011 if(backtrackList.isType<double>("CPS Minimum Step"))
01012 ps_backtrackList.set("Minimum Step", backtrackList.get<double>("CPS Minimum Step"));
01013 if(backtrackList.isType<double>("CPS Recovery Step"))
01014 ps_backtrackList.set("Recovery Step", backtrackList.get<double>("CPS Recovery Step"));
01015
01016
01017
01018
01019
01020
01021
01022 if(xmlOutputFile.length() > 0 && solverComm->MyPID() == 0)
01023 Teuchos::writeParameterListToXmlFile(*ps_appParams, xmlOutputFile);
01024
01025 return ps_appParams;
01026 }
01027
01028 Teuchos::RCP<const Epetra_Map> QCAD::Solver::get_x_map() const
01029 {
01030 Teuchos::RCP<const Epetra_Map> neverused;
01031 return neverused;
01032 }
01033
01034 Teuchos::RCP<const Epetra_Map> QCAD::Solver::get_f_map() const
01035 {
01036 Teuchos::RCP<const Epetra_Map> neverused;
01037 return neverused;
01038 }
01039
01040 Teuchos::RCP<const Epetra_Map> QCAD::Solver::get_p_map(int l) const
01041 {
01042 TEUCHOS_TEST_FOR_EXCEPTION(l >= num_p || l < 0, Teuchos::Exceptions::InvalidParameter,
01043 std::endl <<
01044 "Error in QCAD::Solver::get_p_map(): " <<
01045 "Invalid parameter index l = " <<
01046 l << std::endl);
01047
01048 return epetra_param_map;
01049 }
01050
01051 Teuchos::RCP<const Epetra_Map> QCAD::Solver::get_g_map(int j) const
01052 {
01053 TEUCHOS_TEST_FOR_EXCEPTION(j > num_g || j < 0, Teuchos::Exceptions::InvalidParameter,
01054 std::endl <<
01055 "Error in QCAD::Solver::get_g_map(): " <<
01056 "Invalid response index j = " <<
01057 j << std::endl);
01058
01059 if (j < num_g) return epetra_response_map;
01060 else if (j == num_g) return epetra_x_map;
01061 return Teuchos::null;
01062 }
01063
01064 Teuchos::RCP<const Epetra_Vector> QCAD::Solver::get_x_init() const
01065 {
01066 TEUCHOS_TEST_FOR_EXCEPTION(true, Teuchos::Exceptions::InvalidParameter,
01067 "QCAD::Solver get_x_init() called but it shouldn't be");
01068 return saved_initial_guess;
01069 }
01070
01071 Teuchos::RCP<const Epetra_Vector> QCAD::Solver::get_p_init(int l) const
01072 {
01073 TEUCHOS_TEST_FOR_EXCEPTION(l >= num_p || l < 0, Teuchos::Exceptions::InvalidParameter,
01074 std::endl <<
01075 "Error in QCAD::Solver::get_p_init(): " <<
01076 "Invalid parameter index l = " <<
01077 l << std::endl);
01078
01079
01080 Teuchos::RCP<Epetra_Vector> p_init =
01081 Teuchos::rcp(new Epetra_Vector(*(epetra_param_vec)));
01082
01083 return p_init;
01084 }
01085
01086 EpetraExt::ModelEvaluator::InArgs QCAD::Solver::createInArgs() const
01087 {
01088 EpetraExt::ModelEvaluator::InArgsSetup inArgs;
01089 inArgs.setModelEvalDescription("QCAD Solver Model Evaluator Description");
01090 inArgs.set_Np(num_p);
01091 return inArgs;
01092 }
01093
01094 EpetraExt::ModelEvaluator::OutArgs QCAD::Solver::createOutArgs() const
01095 {
01096
01097 EpetraExt::ModelEvaluator::OutArgsSetup outArgs;
01098 outArgs.setModelEvalDescription("QCAD Solver Multipurpose Model Evaluator");
01099
01100 outArgs.set_Np_Ng(num_p, num_g+1);
01101
01102
01103 if(bSupportDpDg) {
01104 for (int i=0; i<num_g; i++) {
01105 for (int j=0; j<num_p; j++)
01106 outArgs.setSupports(OUT_ARG_DgDp, i, j, deriv_support);
01107 }
01108 }
01109
01110 return outArgs;
01111 }
01112
01113 void
01114 QCAD::Solver::evalModel(const InArgs& inArgs,
01115 const OutArgs& outArgs ) const
01116 {
01117 std::vector<double> eigenvalueResponses;
01118 std::map<std::string, SolverSubSolver> subSolvers;
01119 Teuchos::RCP<Teuchos::FancyOStream> out(Teuchos::VerboseObjectBase::getDefaultOStream());
01120
01121 if(bVerbose) {
01122 if(num_p > 0) {
01123 Teuchos::RCP<const Epetra_Vector> p = inArgs.get_p(0);
01124 *out << "BEGIN QCAD Solver Parameters:" << std::endl;
01125 for(std::size_t i=0; i<nParameters; i++)
01126 *out << " Parameter " << i << " = " << (*p)[i] << std::endl;
01127 *out << "END QCAD Solver Parameters" << std::endl;
01128 }
01129 }
01130
01131 if( problemNameBase == "Poisson" ) {
01132 if(bVerbose) *out << "QCAD Solve: Simple Poisson solve" << std::endl;
01133
01134
01135 subSolvers[ "Poisson" ] = CreateSubSolver( getSubSolverParams("Poisson") , *solverComm, saved_initial_guess);
01136 fillSingleSubSolverParams(inArgs, "Poisson", subSolvers[ "Poisson" ]);
01137
01138 QCAD::SolveModel(subSolvers["Poisson"]);
01139 eigenvalueResponses.resize(0);
01140 }
01141
01142 else if( problemNameBase == "Schrodinger" ) {
01143 if(bVerbose) *out << "QCAD Solve: Simple Schrodinger solve" << std::endl;
01144
01145
01146 subSolvers[ "Schrodinger" ] = CreateSubSolver( getSubSolverParams("Schrodinger") , *solverComm);
01147 fillSingleSubSolverParams(inArgs, "Schrodinger", subSolvers[ "Schrodinger" ]);
01148
01149 Teuchos::RCP<Albany::EigendataStruct> eigenData = Teuchos::null;
01150 Teuchos::RCP<Albany::EigendataStruct> eigenDataNull = Teuchos::null;
01151
01152 QCAD::SolveModel(subSolvers["Schrodinger"], eigenDataNull, eigenData);
01153 eigenvalueResponses = *(eigenData->eigenvalueRe);
01154 for(std::size_t i=0; i<eigenvalueResponses.size(); ++i) eigenvalueResponses[i] *= -1;
01155
01156
01157 Teuchos::RCP<Epetra_Vector> solnVec = subSolvers["Schrodinger"].responses_out->get_g(1);
01158 Teuchos::RCP<MultiSolution_Observer> final_obs =
01159 Teuchos::rcp(new QCAD::MultiSolution_Observer(subSolvers["Schrodinger"].app, mainAppParams));
01160 final_obs->observeSolution(*solnVec, "ZeroSolution", eigenData, 0.0);
01161 }
01162
01163 else if( problemNameBase == "Poisson Schrodinger" )
01164 evalPoissonSchrodingerModel(inArgs, outArgs, eigenvalueResponses, subSolvers);
01165
01166 else if( problemNameBase == "Schrodinger CI" )
01167 evalCIModel(inArgs, outArgs, eigenvalueResponses, subSolvers);
01168
01169 else if( problemNameBase == "Poisson Schrodinger CI" )
01170 evalPoissonCIModel(inArgs, outArgs, eigenvalueResponses, subSolvers);
01171
01172 if(num_g > 0) {
01173
01174 Teuchos::RCP<Epetra_Vector> g = outArgs.get_g(0);
01175 Teuchos::RCP<Epetra_MultiVector> dgdp = Teuchos::null;
01176
01177 if(num_p > 0 && !outArgs.supports(OUT_ARG_DgDp, 0, 0).none())
01178 dgdp = outArgs.get_DgDp(0,0).getMultiVector();
01179
01180 int offset = 0;
01181 std::vector<Teuchos::RCP<QCAD::SolverResponseFn> >::const_iterator rit;
01182
01183 for(rit = responseFns.begin(); rit != responseFns.end(); rit++) {
01184 (*rit)->fillSolverResponses( *g, dgdp, offset, subSolvers, paramFnVecs, bSupportDpDg, eigenvalueResponses);
01185 offset += (*rit)->getNumDoubles();
01186 }
01187
01188 if(bVerbose) {
01189 *out << "BEGIN QCAD Solver Responses:" << std::endl;
01190 for(int i=0; i< g->MyLength(); i++)
01191 *out << " Response " << i << " = " << (*g)[i] << std::endl;
01192 *out << "END QCAD Solver Responses" << std::endl;
01193
01194
01195
01196
01197
01198
01199
01200 }
01201 }
01202 }
01203
01204
01205 void
01206 QCAD::Solver::evalPoissonSchrodingerModel(const InArgs& inArgs,
01207 const OutArgs& outArgs,
01208 std::vector<double>& eigenvalueResponses,
01209 std::map<std::string, SolverSubSolver>& subSolvers) const
01210 {
01211 Teuchos::RCP<Teuchos::FancyOStream> out(Teuchos::VerboseObjectBase::getDefaultOStream());
01212 Teuchos::RCP<Albany::EigendataStruct> eigenDataToPass = Teuchos::null;
01213
01214
01215 bool bConverged = doPSLoop("mix", inArgs, subSolvers, eigenDataToPass, true);
01216
01217 eigenvalueResponses = *(eigenDataToPass->eigenvalueRe);
01218 for(std::size_t i=0; i<eigenvalueResponses.size(); ++i) eigenvalueResponses[i] *= -1;
01219
01220 if(!bUseIntegratedPS) {
01221 if(bConverged) {
01222
01223 Teuchos::RCP<Epetra_Vector> solnVec = subSolvers["Poisson"].responses_out->get_g(1);
01224 Teuchos::RCP<MultiSolution_Observer> final_obs =
01225 Teuchos::rcp(new QCAD::MultiSolution_Observer(subSolvers["Poisson"].app, mainAppParams));
01226 final_obs->observeSolution(*solnVec, "solution", eigenDataToPass, 0.0);
01227 }
01228 }
01229
01230 else {
01231
01232
01233
01234
01235 if(bVerbose) *out << "QCAD Solve: Integrated Poisson-Schrodinger solve started." << std::endl;
01236
01237
01238 const Teuchos::RCP<Teuchos::ParameterList>& ps_paramList = getSubSolverParams("PoissonSchrodinger");
01239 const Teuchos::RCP<QCAD::CoupledPoissonSchrodinger> ps_dummy =
01240 Teuchos::rcp(new QCAD::CoupledPoissonSchrodinger( ps_paramList, solverComm, Teuchos::null));
01241
01242 Teuchos::RCP<const Epetra_Map> combinedMap = ps_dummy->get_x_map();
01243
01244
01245 Teuchos::RCP<Epetra_Vector> initial_guess = Teuchos::rcp(new Epetra_Vector(*combinedMap));
01246 Teuchos::RCP<Epetra_Vector> initial_poisson, initial_evals;
01247 Teuchos::RCP<Epetra_MultiVector> initial_schrodinger;
01248 ps_dummy->separateCombinedVector(initial_guess, initial_poisson, initial_schrodinger, initial_evals);
01249
01250 Teuchos::RCP<Epetra_Vector> poisson_soln = subSolvers["Poisson"].responses_out->get_g(1);
01251 initial_poisson->Scale(1.0, *poisson_soln);
01252
01253
01254
01255 Teuchos::RCP<Albany::AbstractDiscretization> disc = subSolvers["Poisson"].app->getDiscretization();
01256 Teuchos::RCP<const Epetra_Map> disc_map = disc->getMap();
01257 Teuchos::RCP<const Epetra_Map> disc_overlap_map = disc->getOverlapMap();
01258 Teuchos::RCP<Epetra_Export> overlap_exporter = Teuchos::rcp(new Epetra_Export(*disc_overlap_map, *disc_map));
01259
01260 int nEigenvals = initial_schrodinger->NumVectors();
01261 for(int k=0; k < nEigenvals; k++)
01262 (*initial_schrodinger)(k)->Export( *((*(eigenDataToPass->eigenvectorRe))(k)), *overlap_exporter, Insert);
01263
01264 double ignored_norm;
01265 std::vector<int> myGlobalEls( initial_evals->MyLength() );
01266 initial_evals->Map().MyGlobalElements(&myGlobalEls[0]);
01267 for(std::size_t k=0; k < myGlobalEls.size(); k++) {
01268 (*initial_evals)[k] = (*(eigenDataToPass->eigenvalueRe))[ myGlobalEls[k] ];
01269
01270 (*(eigenDataToPass->eigenvectorIm))(myGlobalEls[k])->Norm2(&ignored_norm);
01271 if(ignored_norm > 1e-6) {
01272 std::cout << "QCAD::Solver Warning: ignored imaginary part with norm = "
01273 << ignored_norm << std::endl;
01274 }
01275 }
01276
01277 subSolvers[ "PoissonSchrodinger" ] = CreateSubSolver( getSubSolverParams("PoissonSchrodinger") , *solverComm, initial_guess);
01278 fillSingleSubSolverParams(inArgs, "Poisson", subSolvers[ "PoissonSchrodinger" ], 1);
01279 QCAD::SolveModel(subSolvers["PoissonSchrodinger"]);
01280
01281
01282 Teuchos::RCP<Epetra_Vector> solutionVec = outArgs.get_g(1);
01283 Teuchos::RCP<Epetra_Vector> soln_poisson, soln_evals;
01284 Teuchos::RCP<Epetra_MultiVector> soln_schrodinger;
01285 ps_dummy->separateCombinedVector(solutionVec, soln_poisson, soln_schrodinger, soln_evals);
01286
01287 Epetra_LocalMap local_eigenval_map(nEigenvals, 0, *solverComm);
01288 Epetra_Import eigenval_importer(local_eigenval_map, soln_evals->Map());
01289
01290 Teuchos::RCP<Epetra_Vector> eigenvals = Teuchos::rcp(new Epetra_Vector(local_eigenval_map));
01291 eigenvals->Import(*soln_evals, eigenval_importer, Insert);
01292 eigenvalueResponses = std::vector<double>(&(*eigenvals)[0], &(*eigenvals)[0] + nEigenvals);
01293 for(std::size_t i=0; i<eigenvalueResponses.size(); ++i) eigenvalueResponses[i] *= -1;
01294 }
01295
01296
01297
01298
01299
01300
01301
01302
01303
01304
01305
01306
01307
01308
01309
01310
01311
01312
01313
01314
01315
01316
01317
01318
01319
01320
01321
01322
01323
01324
01325
01326 }
01327
01328
01329 void
01330 QCAD::Solver::evalCIModel(const InArgs& inArgs,
01331 const OutArgs& outArgs,
01332 std::vector<double>& eigenvalueResponses,
01333 std::map<std::string, SolverSubSolver>& subSolvers) const
01334 {
01335 #ifdef ALBANY_CI
01336 Teuchos::RCP<Teuchos::FancyOStream> out(Teuchos::VerboseObjectBase::getDefaultOStream());
01337
01338
01339 Albany::StateArrays* pStatesToPass = NULL;
01340 Albany::StateArrays* pStatesToLoop = NULL;
01341 Teuchos::RCP<Albany::EigendataStruct> eigenDataToPass = Teuchos::null;
01342 Teuchos::RCP<Albany::EigendataStruct> eigenDataNull = Teuchos::null;
01343
01344
01345 std::map<std::string, Teuchos::RCP<Teuchos::ParameterList> >::const_iterator itp;
01346 for(itp = subProblemAppParams.begin(); itp != subProblemAppParams.end(); ++itp) {
01347 const std::string& name = itp->first;
01348 const Teuchos::RCP<Teuchos::ParameterList>& param_list = itp->second;
01349 subSolvers[ name ] = CreateSubSolver( param_list , *solverComm);
01350 }
01351
01352
01353
01354
01355
01356
01357
01358
01359
01360 int n1PperBlock = nEigenvectors;
01361 QCAD::CISolver ciSolver(n1PperBlock, solverComm, out);
01362 Teuchos::RCP<Teuchos::ParameterList> ciParams = ciSolver.getDefaultParameterList();
01363 ciParams->set("Num Excitations", nCIExcitations);
01364 ciParams->set("Subbasis Particles 0", nCIParticles);
01365
01366 if(bUseTotalSpinSymmetry) {
01367 ciParams->set("Num Symmetries", 2);
01368 ciParams->set("Symmetry 0", "Sz");
01369 ciParams->set("Symmetry 1", "S2");
01370 }
01371
01372 if(bVerbose) *out << "QCAD Solve: CI solve" << std::endl;
01373
01374
01375 if(bVerbose) *out << "QCAD Solve: Schrodinger solve" << std::endl;
01376
01377 QCAD::SolveModel(subSolvers["Schrodinger"], pStatesToLoop, pStatesToPass,
01378 eigenDataNull, eigenDataToPass);
01379
01380 Teuchos::RCP<Epetra_Vector> rcp_nullvec = Teuchos::null;
01381
01382
01383 ciSolver.fill1Pmx(eigenDataToPass);
01384 if(!bRealEvecs) {
01385 ciSolver.fill2Pmx(eigenDataToPass, &subSolvers["CoulombPoisson"],
01386 &subSolvers["CoulombPoissonIm"], rcp_nullvec, bRealEvecs, bVerbose);
01387 }
01388 else {
01389 ciSolver.fill2Pmx(eigenDataToPass, &subSolvers["CoulombPoisson"],
01390 NULL, rcp_nullvec, bRealEvecs, bVerbose);
01391 }
01392
01393
01394 if(bVerbose) *out << "QCAD Solve: CI solve" << std::endl;
01395
01396 Teuchos::RCP<AlbanyCI::Solution> soln;
01397 soln = ciSolver.Solve(ciParams);
01398
01399
01400 std::vector<double> eigenvalues = soln->getEigenvalues();
01401 eigenvalueResponses = eigenvalues;
01402 int nCIevals = std::min(eigenvalues.size(),(std::size_t)nEigenvectors);
01403
01404
01405
01406
01407 Teuchos::RCP<Epetra_MultiVector> mbStateDensities = ciSolver.ComputeStateDensities(eigenDataToPass, soln);
01408 eigenDataToPass->eigenvectorRe = mbStateDensities;
01409 eigenDataToPass->eigenvectorIm = mbStateDensities;
01410
01411
01412 eigenDataToPass->eigenvalueRe->resize(nCIevals);
01413 for(int k=0; k < nCIevals; k++)
01414 (*(eigenDataToPass->eigenvalueRe))[k] = eigenvalues[k];
01415
01416 if(eigenDataToPass->eigenvalueIm != Teuchos::null) {
01417 eigenDataToPass->eigenvalueIm->resize(nCIevals);
01418 for(int k=0; k < nCIevals; k++)
01419 (*(eigenDataToPass->eigenvalueIm))[k] = 0.0;
01420 }
01421
01422 if(bVerbose) *out << "-----> CI solve finished." << std::endl;
01423
01424
01425 Teuchos::RCP<Epetra_Vector> solnVec = subSolvers["Schrodinger"].responses_out->get_g(1);
01426 Teuchos::RCP<MultiSolution_Observer> final_obs =
01427 Teuchos::rcp(new QCAD::MultiSolution_Observer(subSolvers["Schrodinger"].app, mainAppParams));
01428 final_obs->observeSolution(*solnVec, "ZeroSolution", eigenDataToPass, 0.0);
01429
01430 #else
01431
01432 TEUCHOS_TEST_FOR_EXCEPTION(true, Teuchos::Exceptions::InvalidParameter,
01433 "Albany must be built with ALBANY_CI enabled in order to perform CI solutions." << std::endl);
01434
01435 #endif
01436 }
01437
01438
01439
01440 void
01441 QCAD::Solver::evalPoissonCIModel(const InArgs& inArgs,
01442 const OutArgs& outArgs,
01443 std::vector<double>& eigenvalueResponses,
01444 std::map<std::string, SolverSubSolver>& subSolvers) const
01445 {
01446 #ifdef ALBANY_CI
01447 Teuchos::RCP<Teuchos::FancyOStream> out(Teuchos::VerboseObjectBase::getDefaultOStream());
01448 Teuchos::RCP<Albany::EigendataStruct> eigenDataNull = Teuchos::null;
01449 Teuchos::RCP<Albany::EigendataStruct> eigenDataToPass = Teuchos::null;
01450
01451
01452 int n1PperBlock = nEigenvectors;
01453 QCAD::CISolver ciSolver(n1PperBlock, solverComm, out);
01454 Teuchos::RCP<Teuchos::ParameterList> ciParams = ciSolver.getDefaultParameterList();
01455
01456 if(bUseTotalSpinSymmetry) {
01457 ciParams->set("Num Symmetries", 2);
01458 ciParams->set("Symmetry 0", "Sz");
01459 ciParams->set("Symmetry 1", "S2");
01460 }
01461
01462 eigenvalueResponses.resize(0);
01463
01464
01465
01466
01467
01468 bool bPoissonSchrodingerConverged = doPSLoop("mix", inArgs, subSolvers, eigenDataToPass, true);
01469 bool bCIConverged = false;
01470 std::size_t iter = 0;
01471
01472
01473 if(bPoissonSchrodingerConverged) {
01474
01475
01476 Teuchos::RCP<Epetra_Vector> g = subSolvers["Poisson"].responses_out->get_g(0);
01477
01478 double nParticlesInQR, deltaFactor;
01479 int nParticles, nExcitations;
01480 int totalQuantumElectronsResponseIndex = g->GlobalLength() - 6;
01481
01482 nParticlesInQR = (*g)[totalQuantumElectronsResponseIndex];
01483 nParticles = std::max((int)round(nParticlesInQR), minCIParticles);
01484 nParticles = std::min(nParticles, maxCIParticles);
01485 if(nParticlesInQR > 0.001)
01486 deltaFactor = ((double)nParticles) / nParticlesInQR;
01487 else deltaFactor = 1.0;
01488
01489 nExcitations = std::min(nParticles,4);
01490 ciParams->set("Num Excitations", nExcitations);
01491 ciParams->set("Subbasis Particles 0", nParticles);
01492
01493 if(nParticles <= 0) {
01494 if(bVerbose) *out << "QCAD Solve: SP Converged. " << nParticlesInQR << " electrons in QR. "
01495 << "Not starting CI since there are no particles (electrons)." << std::endl;
01496 }
01497 else {
01498 if(bVerbose) *out << "QCAD Solve: SP Converged. " << nParticlesInQR << " electrons in QR. Starting CI with "
01499 << nParticles << " particles, " << nExcitations << " excitations" << std::endl;
01500 }
01501
01502 Albany::StateArrays* pStatesToPass = NULL;
01503 Albany::StateArrays* pStatesToLoop = NULL;
01504 Teuchos::RCP<Teuchos::ParameterList> eigList;
01505 double newShift;
01506
01507 while(!bCIConverged) {
01508
01509 if(nParticles > 0) {
01510
01511
01512
01513
01514
01515
01516 Teuchos::RCP<Albany::EigendataStruct> eigenDataNull = Teuchos::null;
01517
01518
01519
01520
01521 if(bVerbose) *out << "QCAD Solve: No-charge Poisson computation" << std::endl;
01522 subSolvers[ "NoChargePoisson" ] = CreateSubSolver( getSubSolverParams("NoChargePoisson") , *solverComm);
01523 fillSingleSubSolverParams(inArgs, "Poisson", subSolvers[ "NoChargePoisson" ]);
01524 QCAD::SolveModel(subSolvers[ "NoChargePoisson" ], eigenDataToPass, eigenDataNull);
01525 Teuchos::RCP<Epetra_Vector> g_noCharge = subSolvers[ "NoChargePoisson" ].responses_out->get_g(0);
01526 subSolvers[ "NoChargePoisson" ].freeUp();
01527
01528
01529 if(bVerbose) *out << "QCAD Solve: Delta Poisson computation" << std::endl;
01530 subSolvers[ "DeltaPoisson" ] = CreateSubSolver( getSubSolverParams("DeltaPoisson") , *solverComm);
01531 fillSingleSubSolverParams(inArgs, "Poisson", subSolvers[ "DeltaPoisson" ]);
01532 QCAD::SolveModel(subSolvers[ "DeltaPoisson" ], eigenDataToPass, eigenDataNull);
01533 Teuchos::RCP<Epetra_Vector> g_delta = subSolvers[ "DeltaPoisson" ].responses_out->get_g(0);
01534 subSolvers[ "DeltaPoisson" ].freeUp();
01535
01536 ciSolver.fill1Pmx(eigenDataToPass, g_noCharge, g_delta, deltaFactor, bRealEvecs, bVerbose);
01537
01538
01539 subSolvers[ "CoulombPoisson" ] = CreateSubSolver( getSubSolverParams("CoulombPoisson") , *solverComm);
01540 fillSingleSubSolverParams(inArgs, "Poisson", subSolvers[ "CoulombPoisson" ]);
01541
01542 if(!bRealEvecs) {
01543 subSolvers[ "CoulombPoissonIm" ] = CreateSubSolver( getSubSolverParams("CoulombPoissonIm") , *solverComm);
01544 fillSingleSubSolverParams(inArgs, "Poisson", subSolvers[ "CoulombPoissonIm" ]);
01545 ciSolver.fill2Pmx(eigenDataToPass, &subSolvers["CoulombPoisson"], &subSolvers["CoulombPoissonIm"],
01546 g_noCharge, bRealEvecs, bVerbose);
01547 subSolvers[ "CoulombPoissonIm" ].freeUp();
01548 }
01549 else {
01550 ciSolver.fill2Pmx(eigenDataToPass, &subSolvers["CoulombPoisson"], NULL,
01551 g_noCharge, bRealEvecs, bVerbose);
01552 }
01553 subSolvers[ "CoulombPoisson" ].freeUp();
01554
01555
01556 if(bVerbose) *out << "QCAD Solve: CI solve" << std::endl;
01557
01558 Teuchos::RCP<AlbanyCI::Solution> soln;
01559 soln = ciSolver.Solve(ciParams);
01560
01561
01562 if(bVerbose) *out << "-----> CI solve finished." << std::endl;
01563
01564 std::vector<double> eigenvalues = soln->getEigenvalues();
01565 eigenvalueResponses = eigenvalues;
01566 int nCIevals = std::min(eigenvalues.size(),(std::size_t)nEigenvectors);
01567
01568
01569
01570
01571 Teuchos::RCP<Epetra_MultiVector> mbStateDensities = ciSolver.ComputeStateDensities(eigenDataToPass, soln);
01572 eigenDataToPass->eigenvectorRe = mbStateDensities;
01573 eigenDataToPass->eigenvectorIm = mbStateDensities;
01574
01575
01576 eigenDataToPass->eigenvalueRe->resize(nCIevals);
01577 for(int k=0; k < nCIevals; k++)
01578 (*(eigenDataToPass->eigenvalueRe))[k] = eigenvalues[k];
01579
01580 if(eigenDataToPass->eigenvalueIm != Teuchos::null) {
01581 eigenDataToPass->eigenvalueIm->resize(nCIevals);
01582 for(int k=0; k < nCIevals; k++)
01583 (*(eigenDataToPass->eigenvalueIm))[k] = 0.0;
01584 }
01585
01586 }
01587 else {
01588
01589
01590 if(bVerbose) *out << "QCAD Solve: Skipping CI solve (no particles)" << std::endl;
01591 eigenDataToPass->eigenvalueRe->resize(0);
01592 if(eigenDataToPass->eigenvalueIm != Teuchos::null)
01593 eigenDataToPass->eigenvalueIm->resize(0);
01594 }
01595
01596
01597
01598 Teuchos::RCP<Epetra_Vector> last_solnVec = subSolvers["Poisson"].responses_out->get_g(1);
01599 subSolvers[ "CIPoisson" ] = CreateSubSolver( getSubSolverParams("CIPoisson") , *solverComm, last_solnVec);
01600 fillSingleSubSolverParams(inArgs, "Poisson", subSolvers[ "CIPoisson" ]);
01601
01602 if(bVerbose) *out << "QCAD Solve: CI Poisson iteration " << iter << std::endl;
01603 QCAD::SolveModel(subSolvers["CIPoisson"], pStatesToPass, pStatesToLoop,
01604 eigenDataToPass, eigenDataNull);
01605
01606
01607 bCIConverged = true;
01608
01609 if(!bCIConverged) {
01610 if(eigensolverName == "LOCA") {
01611 newShift = QCAD::GetEigensolverShift(subSolvers["CIPoisson"], shiftPercentBelowMin);
01612 QCAD::ResetEigensolverShift(subSolvers["Schrodinger"].model, newShift, eigList);
01613 }
01614
01615
01616 if(bVerbose) *out << "QCAD Solve: Schrodinger iteration " << iter << std::endl;
01617 QCAD::SolveModel(subSolvers["Schrodinger"], pStatesToLoop, pStatesToPass,
01618 eigenDataNull, eigenDataToPass);
01619
01620
01621
01622
01623 }
01624
01625 }
01626 }
01627
01628 if(bVerbose) {
01629 if(bCIConverged)
01630 *out << "QCAD Solve: Converged Poisson-CI solve loop after " << iter << " iterations." << std::endl;
01631 else
01632 *out << "QCAD Solve: Maximum iterations (" << maxIter << ") reached." << std::endl;
01633 }
01634
01635 if(bCIConverged) {
01636
01637
01638
01639
01640 printResponses(subSolvers["CIPoisson"], "CIPoisson", out);
01641
01642
01643 Teuchos::RCP<Epetra_Vector> solnVec = subSolvers["CIPoisson"].responses_out->get_g(1);
01644 Teuchos::RCP<MultiSolution_Observer> final_obs =
01645 Teuchos::rcp(new QCAD::MultiSolution_Observer(subSolvers["CIPoisson"].app, mainAppParams));
01646 final_obs->observeSolution(*solnVec, "solution", eigenDataToPass, 0.0);
01647 }
01648
01649
01650 #else
01651
01652 TEUCHOS_TEST_FOR_EXCEPTION(true, Teuchos::Exceptions::InvalidParameter,
01653 "Albany must be built with ALBANY_CI enabled in order to perform Poisson-CI iterative solutions." << std::endl);
01654
01655 #endif
01656 }
01657
01658 bool QCAD::Solver::doPSLoop(const std::string& mode, const InArgs& inArgs,
01659 std::map<std::string, SolverSubSolver>& subSolvers,
01660 Teuchos::RCP<Albany::EigendataStruct>& eigenDataResult,
01661 bool bPrintNumOfQuantumElectrons) const
01662 {
01663 Teuchos::RCP<Teuchos::FancyOStream> out(Teuchos::VerboseObjectBase::getDefaultOStream());
01664
01665
01666 Albany::StateArrays* pStatesToPass = NULL;
01667 Albany::StateArrays* pStatesToLoop = NULL;
01668 Teuchos::RCP<Albany::EigendataStruct> eigenDataNull = Teuchos::null;
01669 eigenDataResult = Teuchos::null;
01670
01671
01672 std::vector<Intrepid::FieldContainer<RealType> > acceptedSolution;
01673 std::vector<Intrepid::FieldContainer<RealType> > acceptedDensity;
01674 std::vector<Intrepid::FieldContainer<RealType> > trialSolution;
01675 std::vector<Intrepid::FieldContainer<RealType> > trialDensity;
01676 std::vector<Intrepid::FieldContainer<RealType> > mixDensity;
01677 std::vector<Intrepid::FieldContainer<RealType> > prevConductionBand;
01678
01679
01680 subSolvers[ "InitPoisson" ] = CreateSubSolver( getSubSolverParams("InitPoisson") , *solverComm, saved_initial_guess);
01681 fillSingleSubSolverParams(inArgs, "Poisson", subSolvers[ "InitPoisson" ], 1);
01682
01683 if(bVerbose) *out << "QCAD Solve: Initial Poisson solve (no quantum region) " << std::endl;
01684 QCAD::SolveModel(subSolvers["InitPoisson"], pStatesToPass, pStatesToLoop);
01685
01686
01687 subSolvers[ "Schrodinger" ] = CreateSubSolver( getSubSolverParams("Schrodinger") , *solverComm);
01688 fillSingleSubSolverParams(inArgs, "Schrodinger", subSolvers[ "Schrodinger" ]);
01689
01690
01691 Teuchos::RCP<Epetra_Vector> initial_solnVec = subSolvers["InitPoisson"].responses_out->get_g(1);
01692 subSolvers[ "Poisson" ] = CreateSubSolver( getSubSolverParams("Poisson") , *solverComm, initial_solnVec);
01693 fillSingleSubSolverParams(inArgs, "Poisson", subSolvers[ "Poisson" ]);
01694
01695 if(bVerbose) *out << "QCAD Solve: Beginning Poisson-Schrodinger solve loop" << std::endl;
01696 bool bConverged = false;
01697 std::size_t iter = 0;
01698 double newShift;
01699 double local_maxDiff, global_maxDiff, best_global_maxDiff = 1e100;
01700 std::string ssForShift = "InitPoisson";
01701
01702 bool stepAccepted;
01703 double stepSize = 1.0, minStep = 0.001;
01704 double damping = 0;
01705 int consecutiveAccepts = 0;
01706 const int MIN_ITER = 2;
01707
01708 Teuchos::RCP<Teuchos::ParameterList> eigList;
01709
01710
01711 QCAD::CopyStateToContainer(*pStatesToLoop, "PS Saved Electron Density", trialDensity);
01712 QCAD::CopyStateToContainer(*pStatesToLoop, "PS Saved Solution", trialSolution);
01713 if(mode == "mix") QCAD::CopyStateToContainer(*pStatesToLoop, "PS Saved Solution", acceptedSolution);
01714
01715 while(!bConverged && iter < maxIter)
01716 {
01717 iter++;
01718 stepAccepted = false;
01719 const double STEP_DIVISOR = 2.0;
01720
01721 while(!stepAccepted) {
01722
01723
01724 if(eigensolverName == "LOCA") {
01725 newShift = QCAD::GetEigensolverShift(subSolvers[ssForShift], shiftPercentBelowMin);
01726 QCAD::ResetEigensolverShift(subSolvers["Schrodinger"].model, newShift, eigList);
01727 }
01728
01729 if(mode == "damping" && iter > 1 && damping > 0) {
01730 if(bVerbose) *out << "QCAD Solve: Damping of " << damping << " applied before Schrodinger iteration " << iter << std::endl;
01731 QCAD::AddContainerToState(prevConductionBand, *pStatesToLoop, "PS Conduction Band", damping, 1-damping);
01732 }
01733
01734
01735 if(bVerbose) *out << "QCAD Solve: Schrodinger iteration " << iter << std::endl;
01736 QCAD::SolveModel(subSolvers["Schrodinger"], pStatesToLoop, pStatesToPass,
01737 eigenDataNull, eigenDataResult);
01738
01739
01740 QCAD::CopyContainerToState(trialSolution, *pStatesToPass, "PS Previous Poisson Potential");
01741
01742 if(mode == "damping") {
01743
01744 QCAD::CopyStateToContainer(*pStatesToLoop, "PS Conduction Band", prevConductionBand);
01745 }
01746
01747
01748 if(iter == 1) subSolvers[ "InitPoisson" ].freeUp();
01749
01750
01751 if(bVerbose) *out << "QCAD Solve: Poisson iteration " << iter << std::endl;
01752 QCAD::SetPreviousDensityMixing(subSolvers["Poisson"].params_in, 0.0);
01753 QCAD::SolveModel(subSolvers["Poisson"], pStatesToPass, pStatesToLoop,
01754 eigenDataResult, eigenDataNull);
01755
01756 if(bPrintNumOfQuantumElectrons) {
01757
01758
01759
01760
01761 Teuchos::RCP<Epetra_Vector> g = subSolvers["Poisson"].responses_out->get_g(0);
01762 int totalQuantumElectronsResponseIndex = g->GlobalLength() - 6;
01763
01764 if(bVerbose) *out << "QCAD Solve: Poisson iteration has " << (*g)[totalQuantumElectronsResponseIndex]
01765 << " electrons in the quantum region" << std::endl;
01766 }
01767
01768 eigenDataNull = Teuchos::null;
01769 ssForShift = "Poisson";
01770
01771
01772
01773
01774
01775
01776 local_maxDiff = QCAD::getNorm2Difference(*pStatesToLoop, trialSolution, "PS Saved Solution");
01777 solverComm->SumAll(&local_maxDiff, &global_maxDiff, 1);
01778 int global_nEls, local_nEls = QCAD::getElementCount(trialSolution);
01779 solverComm->SumAll(&local_nEls, &global_nEls, 1);
01780 global_maxDiff /= global_nEls;
01781
01782
01783 if(best_global_maxDiff < global_maxDiff && iter > MIN_ITER) {
01784
01785 if(mode == "damping" && damping < 0.9) {
01786 damping = (1+damping)/2.0;
01787 stepAccepted = true;
01788 }
01789
01790 else if(mode == "mix" && stepSize/STEP_DIVISOR >= minStep) {
01791
01792 if(bVerbose) *out << "QCAD Solve: Step size " << stepSize << " rejected. Diff="
01793 << global_maxDiff << " (tol=" << ps_converge_tol << ")" << std::endl;
01794
01795
01796
01797
01798 stepSize /= STEP_DIVISOR;
01799 stepAccepted = false;
01800 }
01801
01802 else stepAccepted = true;
01803 }
01804 else stepAccepted = true;
01805
01806 if(stepAccepted) {
01807 if(bVerbose) *out << "QCAD Solve: Step size " << stepSize << " accepted. Diff="
01808 << global_maxDiff << " (tol=" << ps_converge_tol << ")" << std::endl;
01809
01810 if(mode == "mix") {
01811
01812 CopyContainer(trialDensity, acceptedDensity);
01813 CopyContainer(trialSolution, acceptedSolution);
01814
01815
01816 QCAD::CopyStateToContainer(*pStatesToLoop, "PS Saved Electron Density", mixDensity);
01817
01818 consecutiveAccepts++;
01819 if(consecutiveAccepts == 3 && stepSize+1e-6 < 1.0) stepSize *= STEP_DIVISOR;
01820 }
01821 }
01822 else consecutiveAccepts = 0;
01823
01824
01825 if(mode == "mix" && stepSize+1e-6 < 1.0) {
01826
01827
01828
01829
01830
01831
01832
01833
01834 QCAD::CopyContainerToState(acceptedDensity, *pStatesToPass, "PS Previous Electron Density");
01835
01836
01837 QCAD::AddContainerToState(mixDensity, *pStatesToPass, "PS Previous Electron Density", stepSize, 1-stepSize);
01838 QCAD::SetPreviousDensityMixing(subSolvers["Poisson"].params_in, 1.0);
01839
01840
01841 if(bVerbose) *out << "QCAD Solve: Poisson re-mix iteration " << iter << " (step = " << stepSize << ")" << std::endl;
01842 QCAD::SolveModel(subSolvers["Poisson"], pStatesToPass, pStatesToLoop,
01843 eigenDataResult, eigenDataNull);
01844 }
01845
01846
01847
01848
01849 QCAD::CopyStateToContainer(*pStatesToLoop, "PS Saved Electron Density", trialDensity);
01850 QCAD::CopyStateToContainer(*pStatesToLoop, "PS Saved Solution", trialSolution);
01851
01852
01853 }
01854
01855 bConverged = (global_maxDiff < ps_converge_tol*(1.0-damping));
01856 if(global_maxDiff < best_global_maxDiff && iter > MIN_ITER) best_global_maxDiff = global_maxDiff;
01857 }
01858
01859
01860 if(bVerbose) {
01861 if(bConverged)
01862 *out << "QCAD Solve: Converged Poisson-Schrodinger solve loop after " << iter << " iterations." << std::endl;
01863 else
01864 *out << "QCAD Solve: Maximum iterations (" << maxIter << ") reached." << std::endl;
01865 }
01866
01867 return bConverged;
01868
01869
01870
01871
01872
01873
01874
01875
01876
01877
01878
01879
01880
01881
01882
01883
01884
01885
01886
01887
01888
01889
01890
01891
01892
01893
01894
01895
01896
01897
01898
01899
01900
01901
01902
01903
01904
01905
01906
01907
01908
01909
01910
01911
01912
01913
01914
01915
01916
01917
01918
01919
01920
01921
01922
01923
01924
01925
01926
01927
01928
01929
01930
01931
01932
01933
01934
01935
01936
01937
01938
01939
01940
01941
01942 }
01943
01944
01945 void QCAD::Solver::setupParameterMapping(const Teuchos::ParameterList& list, const std::string& defaultSubSolver,
01946 const std::map<std::string, SolverSubSolverData>& subSolversData )
01947 {
01948 std::string s;
01949 std::vector<std::string> fnStrings;
01950
01951 if( list.isType<int>("Number") ) {
01952 nParameters = list.get<int>("Number");
01953
01954 for(std::size_t i=0; i<nParameters; i++) {
01955 s = list.get<std::string>(Albany::strint("Parameter",i));
01956 s = QCAD::string_remove_whitespace(s);
01957 fnStrings = QCAD::string_split(s,';',true);
01958
01959 std::vector<Teuchos::RCP<QCAD::SolverParamFn> > fnVec;
01960 for(std::size_t j=0; j<fnStrings.size(); j++)
01961 fnVec.push_back( Teuchos::rcp(new QCAD::SolverParamFn(fnStrings[j], subSolversData)) );
01962
01963 paramFnVecs.push_back( fnVec );
01964 }
01965 }
01966
01967 else {
01968
01969 if( (subSolversData.find(defaultSubSolver)->second).Np > 0 )
01970 nParameters = (subSolversData.find(defaultSubSolver)->second).pLength[0];
01971 else nParameters = 0;
01972
01973 for(std::size_t i=0; i<nParameters; i++) {
01974 std::ostringstream ss;
01975 std::vector<Teuchos::RCP<QCAD::SolverParamFn> > fnVec;
01976
01977 ss << defaultSubSolver << "[" << i << "]";
01978 fnVec.push_back( Teuchos::rcp(new QCAD::SolverParamFn( ss.str(), subSolversData)) );
01979 paramFnVecs.push_back( fnVec );
01980 }
01981 }
01982 }
01983
01984
01985 void QCAD::Solver::setupResponseMapping(const Teuchos::ParameterList& list, const std::string& defaultSubSolver, int nEigenvalues,
01986 const std::map<std::string, SolverSubSolverData>& subSolversData )
01987 {
01988 Teuchos::RCP<QCAD::SolverResponseFn> fn;
01989
01990 if( list.isType<int>("Number") ) {
01991 int number = list.get<int>("Number");
01992 std::string s;
01993
01994 nResponseDoubles = 0;
01995 for(int i=0; i<number; i++) {
01996 s = list.get<std::string>(Albany::strint("Response",i));
01997 fn = Teuchos::rcp(new QCAD::SolverResponseFn(s, subSolversData, nEigenvalues));
01998 nResponseDoubles += fn->getNumDoubles();
01999 responseFns.push_back( fn );
02000 }
02001 }
02002
02003 else {
02004 std::ostringstream ss;
02005 ss << defaultSubSolver << "[:]";
02006 fn = Teuchos::rcp(new QCAD::SolverResponseFn(ss.str(), subSolversData, nEigenvalues));
02007 nResponseDoubles = fn->getNumDoubles();
02008 responseFns.push_back( fn );
02009 }
02010 }
02011
02012 void QCAD::Solver::fillSingleSubSolverParams(const InArgs& inArgs, const std::string& name,
02013 QCAD::SolverSubSolver& subSolver, int nLeaveOffEnd) const
02014 {
02015 if(num_p > 0) {
02016 Teuchos::RCP<const Epetra_Vector> p = inArgs.get_p(0);
02017 std::vector<Teuchos::RCP<QCAD::SolverParamFn> >::const_iterator pit;
02018 for(std::size_t i=0; i<nParameters; i++) {
02019 for(pit = paramFnVecs[i].begin(); pit != paramFnVecs[i].end()-nLeaveOffEnd; pit++) {
02020 (*pit)->fillSingleSubSolverParams((*p)[i], name, subSolver);
02021 }
02022 }
02023 }
02024 }
02025
02026
02027 const Teuchos::RCP<Teuchos::ParameterList>& QCAD::Solver::getSubSolverParams(const std::string& name) const
02028 {
02029 return subProblemAppParams.find(name)->second;
02030 }
02031
02032
02033 QCAD::SolverSubSolver
02034 QCAD::Solver::CreateSubSolver(const Teuchos::RCP<Teuchos::ParameterList> appParams, const Epetra_Comm& comm,
02035 const Teuchos::RCP<const Epetra_Vector>& initial_guess) const
02036 {
02037 using Teuchos::RCP;
02038 using Teuchos::rcp;
02039
02040 QCAD::SolverSubSolver ret;
02041
02042 const Albany_MPI_Comm mpiComm = Albany::getMpiCommFromEpetraComm(comm);
02043
02044 RCP<Teuchos::FancyOStream> out(Teuchos::VerboseObjectBase::getDefaultOStream());
02045 *out << "QCAD Solver creating solver from " << appParams->name()
02046 << " parameter list" << std::endl;
02047
02049 Albany::SolverFactory slvrfctry(appParams, mpiComm);
02050
02052 RCP<Epetra_Comm> appComm = Albany::createEpetraCommFromMpiComm(mpiComm);
02053 ret.model = slvrfctry.createAndGetAlbanyApp(ret.app, appComm, appComm, initial_guess);
02054
02055 ret.params_in = rcp(new EpetraExt::ModelEvaluator::InArgs);
02056 ret.responses_out = rcp(new EpetraExt::ModelEvaluator::OutArgs);
02057
02058 *(ret.params_in) = ret.model->createInArgs();
02059 *(ret.responses_out) = ret.model->createOutArgs();
02060 int ss_num_p = ret.params_in->Np();
02061 int ss_num_g = ret.responses_out->Ng();
02062 RCP<Epetra_Vector> p1;
02063 RCP<Epetra_Vector> g1;
02064
02065 if (ss_num_p > 0)
02066 p1 = rcp(new Epetra_Vector(*(ret.model->get_p_init(0))));
02067 if (ss_num_g > 1)
02068 g1 = rcp(new Epetra_Vector(*(ret.model->get_g_map(0))));
02069 RCP<Epetra_Vector> xfinal =
02070 rcp(new Epetra_Vector(*(ret.model->get_g_map(ss_num_g-1)),true) );
02071
02072
02073 bool supportsSensitivities = false;
02074 RCP<Epetra_MultiVector> dgdp;
02075
02076 if (ss_num_p>0 && ss_num_g>1) {
02077 supportsSensitivities =
02078 !ret.responses_out->supports(EpetraExt::ModelEvaluator::OUT_ARG_DgDp, 0, 0).none();
02079
02080 if (supportsSensitivities) {
02081 if (p1->GlobalLength() > 0)
02082 dgdp = rcp(new Epetra_MultiVector(g1->Map(), p1->GlobalLength() ));
02083 else
02084 supportsSensitivities = false;
02085 }
02086 }
02087
02088 if (ss_num_p > 0) ret.params_in->set_p(0,p1);
02089 if (ss_num_g > 1) ret.responses_out->set_g(0,g1);
02090 ret.responses_out->set_g(ss_num_g-1,xfinal);
02091
02092 if (supportsSensitivities) ret.responses_out->set_DgDp(0,0,dgdp);
02093
02094 return ret;
02095 }
02096
02097 QCAD::SolverSubSolverData
02098 QCAD::Solver::CreateSubSolverData(const QCAD::SolverSubSolver& sub) const
02099 {
02100 QCAD::SolverSubSolverData ret;
02101 if( sub.params_in->Np() > 0 && sub.responses_out->Ng() > 0 ) {
02102 ret.deriv_support = sub.model->createOutArgs().supports(OUT_ARG_DgDp, 0, 0);
02103 }
02104 else ret.deriv_support = EpetraExt::ModelEvaluator::DerivativeSupport();
02105
02106 ret.Np = sub.params_in->Np();
02107 ret.pLength = std::vector<int>(ret.Np);
02108 for(int i=0; i<ret.Np; i++) {
02109 Teuchos::RCP<const Epetra_Vector> solver_p = sub.params_in->get_p(i);
02110 if(solver_p != Teuchos::null) ret.pLength[i] = solver_p->MyLength();
02111 else ret.pLength[i] = 0;
02112 }
02113
02114 ret.Ng = sub.responses_out->Ng();
02115 ret.gLength = std::vector<int>(ret.Ng);
02116 for(int i=0; i<ret.Ng; i++) {
02117 Teuchos::RCP<const Epetra_Vector> solver_g = sub.responses_out->get_g(i);
02118 if(solver_g != Teuchos::null) ret.gLength[i] = solver_g->MyLength();
02119 else ret.gLength[i] = 0;
02120 }
02121
02122 if(ret.Np > 0) {
02123 Teuchos::RCP<const Epetra_Vector> p_init =
02124 sub.model->get_p_init(0);
02125 if(p_init != Teuchos::null) ret.p_init = Teuchos::rcp(new const Epetra_Vector(*p_init));
02126 else ret.p_init = Teuchos::null;
02127 }
02128 else ret.p_init = Teuchos::null;
02129
02130 return ret;
02131 }
02132
02133
02134 void QCAD::Solver::printResponses(const SolverSubSolver& solver, const std::string& solverName, Teuchos::RCP<Teuchos::FancyOStream> out) const
02135 {
02136 int solver_num_p = solver.params_in->Np();
02137 int solver_num_g = solver.responses_out->Ng();
02138
02139 for (int i=0; i<solver_num_p; i++)
02140 solver.params_in->get_p(i)->Print(*out << "\n" << solverName << " Parameter vector " << i << ":\n");
02141
02142 for (int i=0; i<solver_num_g-1; i++) {
02143 Teuchos::RCP<Epetra_Vector> g = solver.responses_out->get_g(i);
02144 bool is_scalar = true;
02145
02146 if (solver.app != Teuchos::null)
02147 is_scalar = solver.app->getResponse(i)->isScalarResponse();
02148
02149 if (is_scalar) {
02150 g->Print(*out << "\n" << solverName << " Response vector " << i << ":\n");
02151 *out << "\n";
02152 }
02153
02154
02155 }
02156 }
02157
02158
02159 Teuchos::RCP<const Teuchos::ParameterList>
02160 QCAD::Solver::getValidProblemParameters() const
02161 {
02162 Teuchos::RCP<Teuchos::ParameterList> validPL = Teuchos::createParameterList("ValidPoissonSchrodingerProblemParams");
02163
02164 validPL->set<std::string>("Name", "", "String to designate Problem");
02165 validPL->set<int>("Phalanx Graph Visualization Detail", 0,
02166 "Flag to select output of Phalanx Graph and level of detail");
02167 validPL->set<bool>("Verbose Output",false,"Enable detailed output mode");
02168 validPL->set<std::string>("Piro Defaults Filename","","An xml file containing a Piro parameterlist and its sublists to use as a default Piro list for this problem");
02169
02170 validPL->set<double>("Length Unit In Meters",1e-6,"Length unit in meters");
02171 validPL->set<double>("Energy Unit In Electron Volts",1.0,"Energy (voltage) unit in electron volts (volts)");
02172 validPL->set<double>("Temperature",300,"Temperature in Kelvin");
02173 validPL->set<std::string>("MaterialDB Filename","materials.xml","Filename of material database xml file");
02174
02175 validPL->set<std::string>("Schrodinger Eigensolver", "LOBPCG", "Name of eigensolver to use in schrodinger solve. Can be LOCA or LOBPCG");
02176 validPL->set<bool>("Eigenvectors are Real",false,"Whether Schrodinger eigenvectors are known to have no imaginary part.");
02177
02178 validPL->set<bool>("Use Integrated Poisson Schrodinger",true,"After converging iterative P-S, run integrated P-S solver");
02179 validPL->set<int>("Number of Eigenvalues",0,"The number of eigenvalue-eigenvector pairs");
02180 validPL->set<int>("Maximum PS Iterations",100,"The maximum number of P-S iterations");
02181 validPL->set<double>("Eigensolver Percent Shift Below Potential Min", 1.0, "Percentage of energy range of potential to subtract from the potential's minimum to obtain the eigensolver's shift");
02182 validPL->set<double>("Iterative PS Convergence Tolerance", 1e-6, "Convergence criterion for iterative PS solver (max potential difference across mesh)");
02183 validPL->set<double>("Iterative PS Fixed Occupation", -1.0, "Fixed quantum orbital occupation for iterative PS solver (non equilibrium condition)");
02184
02185 validPL->set<int>("Minimum CI Particles", 0, "Poisson Schrodinger CI mode only: the minimum number of particles to use in the CI phase");
02186 validPL->set<int>("Maximum CI Particles", 0, "Poisson Schrodinger CI mode only: the maximum number of particles to use in the CI phase");
02187 validPL->set<int>("CI Particles", 0, "Schrodinger CI mode only: the number of particles to use in the CI phase");
02188 validPL->set<int>("CI Excitations", 0, "Schrodinger CI mode only: the number of excitations with which to truncate the CI phase");
02189 validPL->set<bool>("Use S2 Symmetry in CI",false,"Use total spin symmetry in the CI part of a problem");
02190
02191 validPL->set<bool>("Include exchange-correlation potential",false,"Include exchange-correlation potential in poisson source term");
02192 validPL->set<bool>("Only solve schrodinger in quantum blocks",true,"Limit schrodinger solution to elements blocks labeled as quantum in the materials DB");
02193
02194 validPL->set<bool>("Use predictor-corrector method",false,"Enable the predictor corrector algorithm for P-S iteration (otherwise use Picard)");
02195
02196 validPL->sublist("Poisson Problem", false, "");
02197 validPL->sublist("Schrodinger Problem", false, "");
02198 validPL->sublist("Initial Condition", false, "");
02199
02200
02201 const int maxParameters = 100;
02202 Teuchos::ParameterList& validParamPL = validPL->sublist("Parameters", false, "");
02203 validParamPL.set<int>("Number", 0);
02204 for (int i=0; i<maxParameters; i++) {
02205 validParamPL.set<std::string>(Albany::strint("Parameter",i), "");
02206 }
02207
02208
02209 const int maxResponses = 100;
02210 Teuchos::ParameterList& validResponsePL = validPL->sublist("Response Functions", false, "");
02211 validResponsePL.set<int>("Number of Response Vectors", 0);
02212 validResponsePL.set<int>("Number", 0);
02213 validResponsePL.set<int>("Equation", 0);
02214 for (int i=0; i<maxResponses; i++) {
02215 validResponsePL.set<std::string>(Albany::strint("Response",i), "");
02216 validResponsePL.sublist(Albany::strint("ResponseParams",i));
02217 validResponsePL.sublist(Albany::strint("Response Vector",i));
02218 }
02219
02220
02221 validPL->set<std::string>("Solution Method", "Steady", "Flag for Steady, Transient, or Continuation");
02222
02223 return validPL;
02224 }
02225
02226
02227
02228
02230
02232
02233
02234
02235
02236 QCAD::SolverParamFn::SolverParamFn(const std::string& fnString,
02237 const std::map<std::string, QCAD::SolverSubSolverData>& subSolversData)
02238 {
02239 std::vector<std::string> fnsAndTarget = QCAD::string_split(fnString,'>',true);
02240 std::vector<std::string>::const_iterator it;
02241 std::map<std::string,std::string> target;
02242
02243 if( fnsAndTarget.begin() != fnsAndTarget.end() ) {
02244 for(it=fnsAndTarget.begin(); it != fnsAndTarget.end()-1; it++) {
02245 filters.push_back( QCAD::string_parse_function( *it ) );
02246 }
02247 it = fnsAndTarget.end()-1;
02248 target = QCAD::string_parse_arrayref( *it );
02249 targetName = target["name"];
02250
02251 targetIndices = QCAD::string_expand_compoundindex(target["index"], 0,
02252 (subSolversData.find(targetName)->second).pLength[0]);
02253 }
02254 }
02255
02256
02257 void QCAD::SolverParamFn::fillSingleSubSolverParams(double parameterValue, const std::string& subSolverName,
02258 QCAD::SolverSubSolver& subSolver) const
02259 {
02260 if(subSolverName != targetName) return;
02261
02262 std::vector< std::vector<std::string> >::const_iterator fit;
02263 for(fit = filters.begin(); fit != filters.end(); ++fit) {
02264
02265
02266 std::string fnName = (*fit)[0];
02267 if( fnName == "scale" ) {
02268 TEUCHOS_TEST_FOR_EXCEPT( fit->size() != 1+1 );
02269 parameterValue *= atof( (*fit)[1].c_str() );
02270 }
02271 else TEUCHOS_TEST_FOR_EXCEPTION(true, Teuchos::Exceptions::InvalidParameter,
02272 "Unknown function " << (*fit)[0] << " for given type." << std::endl);
02273 }
02274
02275 Teuchos::RCP<EpetraExt::ModelEvaluator::InArgs> inArgs = subSolver.params_in;
02276 Teuchos::RCP<const Epetra_Vector> p_ro = inArgs->get_p(0);
02277 Teuchos::RCP<Epetra_Vector> p = Teuchos::rcp( new Epetra_Vector( *p_ro ) );
02278
02279
02280 std::vector<int>::const_iterator it;
02281 for(it = targetIndices.begin(); it != targetIndices.end(); ++it)
02282 (*p)[ (*it) ] = parameterValue;
02283
02284 inArgs->set_p(0, p);
02285 }
02286
02287
02288
02289 void QCAD::SolverParamFn::fillSubSolverParams(double parameterValue,
02290 const std::map<std::string, QCAD::SolverSubSolver>& subSolvers) const
02291 {
02292 std::vector< std::vector<std::string> >::const_iterator fit;
02293 for(fit = filters.begin(); fit != filters.end(); ++fit) {
02294
02295
02296 std::string fnName = (*fit)[0];
02297 if( fnName == "scale" ) {
02298 TEUCHOS_TEST_FOR_EXCEPT( fit->size() != 1+1 );
02299 parameterValue *= atof( (*fit)[1].c_str() );
02300 }
02301 else TEUCHOS_TEST_FOR_EXCEPTION(true, Teuchos::Exceptions::InvalidParameter,
02302 "Unknown function " << (*fit)[0] << " for given type." << std::endl);
02303 }
02304
02305 Teuchos::RCP<EpetraExt::ModelEvaluator::InArgs> inArgs = (subSolvers.find(targetName)->second).params_in;
02306 Teuchos::RCP<const Epetra_Vector> p_ro = inArgs->get_p(0);
02307 Teuchos::RCP<Epetra_Vector> p = Teuchos::rcp( new Epetra_Vector( *p_ro ) );
02308
02309
02310 std::vector<int>::const_iterator it;
02311 for(it = targetIndices.begin(); it != targetIndices.end(); ++it)
02312 (*p)[ (*it) ] = parameterValue;
02313
02314 inArgs->set_p(0, p);
02315 }
02316
02317 double QCAD::SolverParamFn::
02318 getInitialParam(const std::map<std::string, QCAD::SolverSubSolverData>& subSolversData) const
02319 {
02320
02321 double initVal;
02322
02323 Teuchos::RCP<const Epetra_Vector> p_init =
02324 (subSolversData.find(targetName)->second).p_init;
02325
02326 TEUCHOS_TEST_FOR_EXCEPT(targetIndices.size() == 0);
02327 initVal = (*p_init)[ targetIndices[0] ];
02328
02329 std::vector< std::vector<std::string> >::const_iterator fit;
02330 for(fit = filters.end(); fit != filters.begin(); --fit) {
02331
02332
02333 std::string fnName = (*fit)[0];
02334 if( fnName == "scale" ) {
02335 TEUCHOS_TEST_FOR_EXCEPT( fit->size() != 1+1 );
02336 initVal /= atof( (*fit)[1].c_str() );
02337 }
02338 else TEUCHOS_TEST_FOR_EXCEPTION(true, Teuchos::Exceptions::InvalidParameter,
02339 "Unknown function " << (*fit)[0] << " for given type." << std::endl);
02340 }
02341
02342 return initVal;
02343 }
02344
02345 double QCAD::SolverParamFn::
02346 getFilterScaling() const
02347 {
02348 double scaling = 1.0;
02349
02350 std::vector< std::vector<std::string> >::const_iterator fit;
02351 for(fit = filters.end(); fit != filters.begin(); --fit) {
02352
02353
02354 std::string fnName = (*fit)[0];
02355 if( fnName == "scale" ) {
02356 TEUCHOS_TEST_FOR_EXCEPT( fit->size() != 1+1 );
02357 scaling *= atof( (*fit)[1].c_str() );
02358 }
02359 }
02360 return scaling;
02361 }
02362
02363
02364
02366
02368
02369
02370
02371
02372 QCAD::SolverResponseFn::SolverResponseFn(const std::string& fnString,
02373 const std::map<std::string, QCAD::SolverSubSolverData>& subSolversData,
02374 int nEigenvalues)
02375 {
02376 using std::string;
02377 std::vector<std::string> fnsAndTarget = QCAD::string_split(fnString,'>',true);
02378 std::vector<std::string>::const_iterator it;
02379 std::map<std::string,std::string> arrayRef;
02380 ArrayRef ar;
02381 int nParams = 0;
02382
02383
02384 if( fnString.find_first_of('(') == string::npos ) {
02385 fnName = "nop";
02386 arrayRef = QCAD::string_parse_arrayref( fnString );
02387 ar.name = arrayRef["name"];
02388
02389 if(ar.name == "Eigenvalue") {
02390 ar.indices = QCAD::string_expand_compoundindex(arrayRef["index"], 0, nEigenvalues);
02391 }
02392 else {
02393 ar.indices = QCAD::string_expand_compoundindex(arrayRef["index"], 0, (subSolversData.find(ar.name)->second).gLength[0]);
02394 }
02395 params.push_back(ar);
02396 nParams += ar.indices.size();
02397 }
02398
02399
02400 else {
02401 std::vector<std::string> fnAndParams = QCAD::string_parse_function( fnString );
02402 fnName = fnAndParams[0];
02403
02404 for(std::size_t i=1; i<fnAndParams.size(); i++) {
02405
02406
02407 if( fnAndParams[i].find_first_of('[') == string::npos ) {
02408 ar.name = fnAndParams[i];
02409 ar.indices.clear();
02410 params.push_back(ar);
02411 nParams += 1;
02412 }
02413 else {
02414 arrayRef = QCAD::string_parse_arrayref( fnAndParams[i] );
02415 ar.name = arrayRef["name"];
02416 ar.indices = QCAD::string_expand_compoundindex(arrayRef["index"], 0, (subSolversData.find(ar.name)->second).gLength[0]);
02417
02418 params.push_back(ar);
02419 nParams += ar.indices.size();
02420 }
02421 }
02422 }
02423
02424
02425 if( fnName == "min" || fnName == "max") {
02426 TEUCHOS_TEST_FOR_EXCEPT(nParams != 2);
02427 numDoubles = 1;
02428 }
02429 else if( fnName == "dist") {
02430 TEUCHOS_TEST_FOR_EXCEPT( !(nParams == 2 || nParams == 4 || nParams == 6));
02431 numDoubles = 1;
02432 }
02433 else if( fnName == "scale") {
02434 TEUCHOS_TEST_FOR_EXCEPT(nParams != 2);
02435 numDoubles = 1;
02436 }
02437 else if( fnName == "divide") {
02438 TEUCHOS_TEST_FOR_EXCEPT(nParams != 2);
02439 numDoubles = 1;
02440 }
02441 else if( fnName == "nop") {
02442 numDoubles = nParams;
02443 }
02444 else if( fnName == "DgDp") {
02445 TEUCHOS_TEST_FOR_EXCEPT(nParams != 3);
02446 numDoubles = 1;
02447 }
02448 else TEUCHOS_TEST_FOR_EXCEPTION(true, Teuchos::Exceptions::InvalidParameter,
02449 "Unknown function " << fnName << " for QCAD solver response." << std::endl);
02450
02451 }
02452
02453
02454 void QCAD::SolverResponseFn::fillSolverResponses(Epetra_Vector& g, Teuchos::RCP<Epetra_MultiVector>& dgdp, int offset,
02455 const std::map<std::string, QCAD::SolverSubSolver>& subSolvers,
02456 const std::vector<std::vector<Teuchos::RCP<QCAD::SolverParamFn> > >& paramFnVecs,
02457 bool bSupportDpDg, const std::vector<double>& eigenvalueResponses) const
02458 {
02459 std::size_t nParameters = paramFnVecs.size();
02460
02461
02462 TEUCHOS_TEST_FOR_EXCEPTION(g.DistributedGlobal(), Teuchos::Exceptions::InvalidParameter,
02463 "Error! Solvers's g response vector is distributed. No implementation for this yet."
02464 << std::endl);
02465 if(dgdp != Teuchos::null)
02466 TEUCHOS_TEST_FOR_EXCEPTION(dgdp->DistributedGlobal(), Teuchos::Exceptions::InvalidParameter,
02467 "Error! Solvers's DgDp multivector is distributed. No implementation for this yet."
02468 << std::endl);
02469
02470
02471 std::vector< double > arg_vals;
02472 std::vector< std::vector<double> > arg_DgDps;
02473
02474
02475
02476
02477 std::vector< ArrayRef >::const_iterator arg_it;
02478 std::string dgdpName;
02479
02480
02481 for(arg_it = params.begin(); arg_it != params.end(); ++arg_it) {
02482
02483 if( fnName == "DgDp" && arg_it == params.begin() ) {
02484 dgdpName = arg_it->name; continue;
02485 }
02486
02487 if( arg_it->indices.size() == 0 ){
02488
02489
02490 arg_vals.push_back( atof(arg_it->name.c_str()) );
02491
02492 if(dgdp != Teuchos::null) {
02493 std::vector<double> dgdp_accum(nParameters,0.0);
02494 arg_DgDps.push_back( dgdp_accum );
02495 }
02496 }
02497 else {
02498
02499 std::string solverName = arg_it->name;
02500 Teuchos::RCP<Epetra_Vector> sub_g;
02501 Teuchos::RCP<Epetra_MultiVector> sub_dgdp;
02502
02503
02504 if(solverName == "Eigenvalue") {
02505 std::vector<int>::const_iterator it;
02506 for(it = arg_it->indices.begin(); it != arg_it->indices.end(); ++it) {
02507 arg_vals.push_back( eigenvalueResponses[ *it ]);
02508 if(dgdp != Teuchos::null) {
02509 std::vector<double> dgdp_accum(nParameters,0.0);
02510 arg_DgDps.push_back( dgdp_accum );
02511 }
02512 }
02513 }
02514
02515 else {
02516 const QCAD::SolverSubSolver& solver = subSolvers.find(solverName)->second;
02517 sub_g = solver.responses_out->get_g(0);
02518 if(dgdp != Teuchos::null)
02519 sub_dgdp = solver.responses_out->get_DgDp(0,0).getMultiVector();
02520
02521
02522 std::vector<int>::const_iterator it; int iIndx;
02523 for(it = arg_it->indices.begin(), iIndx=0; it != arg_it->indices.end(); ++it, ++iIndx) {
02524 int gIndex = *it;
02525 arg_vals.push_back( (*sub_g)[ gIndex ]);
02526
02527
02528 if(dgdp != Teuchos::null) {
02529 std::vector<double> dgdp_accum(nParameters,0.0);
02530 for(std::size_t i=0; i<nParameters; i++) {
02531 const std::vector<Teuchos::RCP<QCAD::SolverParamFn> >& paramFnVec = paramFnVecs[i];
02532 for(std::size_t j=0; j<paramFnVec.size(); j++) {
02533 const QCAD::SolverParamFn& paramFn = *(paramFnVec[j]);
02534
02535 std::string paramTargetName = paramFn.getTargetName();
02536 const std::vector<int>& paramTargetIndices = paramFn.getTargetIndices();
02537 double scaling = paramFn.getFilterScaling();
02538
02539 if(paramTargetName != solverName) continue;
02540
02541
02542 std::vector<int>::const_iterator vit;
02543 for(vit = paramTargetIndices.begin(); vit != paramTargetIndices.end(); ++vit)
02544 dgdp_accum[ i ] += (*((*sub_dgdp)( *vit )))[ gIndex ] * scaling;
02545 }
02546 }
02547 arg_DgDps.push_back( dgdp_accum );
02548 }
02549 }
02550 }
02551 }
02552 }
02553
02554
02555
02556
02557
02558
02559
02561 std::size_t nArgs = arg_vals.size();
02562
02563
02564 if( fnName == "min" ) {
02565 int winIndex = (arg_vals[0] <= arg_vals[1]) ? 0 : 1;
02566 g[offset] = arg_vals[winIndex];
02567
02568 if(dgdp != Teuchos::null) {
02569 for(std::size_t i=0; i < arg_DgDps[winIndex].size(); i++)
02570 dgdp->ReplaceGlobalValue(offset, i, arg_DgDps[winIndex][i]);
02571 }
02572 }
02573
02574
02575 else if(fnName == "max") {
02576 int winIndex = (arg_vals[0] >= arg_vals[1]) ? 0 : 1;
02577 g[offset] = arg_vals[winIndex];
02578
02579 if(dgdp != Teuchos::null) {
02580 for(std::size_t i=0; i < arg_DgDps[winIndex].size(); i++)
02581 dgdp->ReplaceGlobalValue(offset, i, arg_DgDps[winIndex][i]);
02582 }
02583 }
02584
02585
02586 else if( fnName == "dist") {
02587 if(nArgs == 2)
02588 g[offset] = abs(arg_vals[0]-arg_vals[1]);
02589 else if(nArgs == 4)
02590 g[offset] = sqrt( pow(arg_vals[0]-arg_vals[2],2) + pow(arg_vals[1]-arg_vals[3],2));
02591 else if(nArgs == 6)
02592 g[offset] = sqrt( pow(arg_vals[0]-arg_vals[3],2) +
02593 pow(arg_vals[1]-arg_vals[4],2) + pow(arg_vals[2]-arg_vals[5],2) );
02594
02595 if(dgdp != Teuchos::null) {
02596 TEUCHOS_TEST_FOR_EXCEPTION(true, Teuchos::Exceptions::InvalidParameter,
02597 "Error! No implementation of derivatives for distance function yet." << std::endl);
02598 }
02599 }
02600
02601
02602 else if( fnName == "scale") {
02603 g[offset] = arg_vals[0] * arg_vals[1];
02604
02605 if(dgdp != Teuchos::null) {
02606 for(std::size_t i=0; i < nParameters; i++) {
02607
02608 dgdp->ReplaceGlobalValue(offset, i, arg_vals[0] * arg_DgDps[1][i] + arg_DgDps[0][i] * arg_vals[1]);
02609 }
02610 }
02611 }
02612
02613
02614 else if( fnName == "divide") {
02615 g[offset] = arg_vals[0] / arg_vals[1];
02616
02617 if(dgdp != Teuchos::null) {
02618 for(std::size_t i=0; i < nParameters; i++) {
02619
02620 dgdp->ReplaceGlobalValue(offset, i, (arg_DgDps[0][i] * arg_vals[1] - arg_vals[0] * arg_DgDps[1][i]) / pow(arg_vals[1],2) );
02621 }
02622 }
02623 }
02624
02625
02626 else if( fnName == "nop") {
02627 for(std::size_t i=0; i < nArgs; i++) {
02628 g[offset+i] = arg_vals[i];
02629
02630 if(dgdp != Teuchos::null) {
02631 for(std::size_t k=0; k < arg_DgDps[i].size(); k++) {
02632 #ifndef EPETRA_NO_32BIT_GLOBAL_INDICES
02633 typedef int GlobalIndex;
02634 #else
02635 typedef long long GlobalIndex;
02636 #endif
02637 dgdp->ReplaceGlobalValue(static_cast<GlobalIndex>(offset+i), k, arg_DgDps[i][k]);
02638 }
02639 }
02640 }
02641 }
02642
02643
02644 else if( fnName == "DgDp") {
02645
02646 if(bSupportDpDg) {
02647 int pIndex = (int)arg_vals[0], gIndex = (int)arg_vals[1];
02648 Teuchos::RCP<Epetra_MultiVector> sub_dgdp =
02649 (subSolvers.find(dgdpName)->second).responses_out->get_DgDp(0,0).getMultiVector();
02650
02651
02652
02653 TEUCHOS_TEST_FOR_EXCEPTION(sub_dgdp->DistributedGlobal(), Teuchos::Exceptions::InvalidParameter,
02654 "Error! sub-solvers's DgDp multivector is distributed. No implementation for this yet."
02655 << std::endl);
02656
02657 g[offset] = (*((*sub_dgdp)(pIndex)))[gIndex];
02658
02659 if(dgdp != Teuchos::null) {
02660 for(std::size_t k=0; k < nParameters; k++)
02661 dgdp->ReplaceGlobalValue(offset,k, 0.0);
02662 }
02663 }
02664 else g[offset] = 0.0;
02665 }
02666
02667 else TEUCHOS_TEST_FOR_EXCEPTION(true, Teuchos::Exceptions::InvalidParameter,
02668 "Unknown function " << fnName << " for QCAD solver response." << std::endl);
02669 }
02670
02671
02672
02673
02674
02675 #ifdef ALBANY_CI
02676
02678
02680
02681 QCAD::CISolver::CISolver(int n1PSpinlessStates, Teuchos::RCP<const Epetra_Comm> eComm,
02682 Teuchos::RCP<Teuchos::FancyOStream> outStream)
02683 :n1PperBlock(n1PSpinlessStates)
02684 {
02685
02686
02687 blockU = Teuchos::rcp(new AlbanyCI::Tensor<AlbanyCI::dcmplx>(n1PperBlock, n1PperBlock));
02688 blockD = Teuchos::rcp(new AlbanyCI::Tensor<AlbanyCI::dcmplx>(n1PperBlock, n1PperBlock));
02689 blocks1P.push_back(blockU); blocks1P.push_back(blockD);
02690
02691
02692 blockUU = Teuchos::rcp(new AlbanyCI::Tensor<AlbanyCI::dcmplx>(n1PperBlock,n1PperBlock,n1PperBlock,n1PperBlock));
02693 blockUD = Teuchos::rcp(new AlbanyCI::Tensor<AlbanyCI::dcmplx>(n1PperBlock,n1PperBlock,n1PperBlock,n1PperBlock));
02694 blockDU = Teuchos::rcp(new AlbanyCI::Tensor<AlbanyCI::dcmplx>(n1PperBlock,n1PperBlock,n1PperBlock,n1PperBlock));
02695 blockDD = Teuchos::rcp(new AlbanyCI::Tensor<AlbanyCI::dcmplx>(n1PperBlock,n1PperBlock,n1PperBlock,n1PperBlock));
02696 blocks2P.push_back(blockUU); blocks2P.push_back(blockUD);
02697 blocks2P.push_back(blockDU); blocks2P.push_back(blockDD);
02698
02699
02700 basis1P = Teuchos::rcp(new AlbanyCI::SingleParticleBasis);
02701 basis1P->init(n1PperBlock , n1PperBlock , true );
02702
02703
02704 comm = Albany::createTeuchosCommFromMpiComm(Albany::getMpiCommFromEpetraComm(*eComm));
02705
02706
02707 out = outStream;
02708
02709
02710
02711
02712
02713 }
02714
02715
02716 Teuchos::RCP<Teuchos::ParameterList>
02717 QCAD::CISolver::getDefaultParameterList() const
02718 {
02719 Teuchos::RCP<Teuchos::ParameterList> defaultPL = Teuchos::rcp( new Teuchos::ParameterList );
02720
02721
02722 int numEvals=n1PperBlock;
02723 int blockSize=n1PperBlock + 1;
02724 int numBlocks=8;
02725
02726 int maxRestarts=100;
02727 double tol = 1e-8;
02728
02729
02730 defaultPL->set("Num Excitations", 0);
02731 defaultPL->set("Num Subbases", 1);
02732 defaultPL->set("Subbasis Particles 0", 0);
02733 defaultPL->set("Num Symmetries", 1);
02734 defaultPL->set("Symmetry 0", "Sz");
02735 defaultPL->set("Num Symmetry Filters", 0);
02736
02737 Teuchos::ParameterList& AnasaziList = defaultPL->sublist("Anasazi");
02738 std::string which("SR");
02739 AnasaziList.set( "Which", which );
02740 AnasaziList.set( "Num Eigenvalues", numEvals );
02741 AnasaziList.set( "Block Size", blockSize );
02742 AnasaziList.set( "Num Blocks", numBlocks );
02743 AnasaziList.set( "Maximum Restarts", maxRestarts );
02744 AnasaziList.set( "Convergence Tolerance", tol );
02745
02746 return defaultPL;
02747 }
02748
02749
02750
02751
02752
02753
02754
02755
02756
02757
02758
02759
02760
02761
02762
02763
02764
02765
02766
02767
02768
02769
02770
02771
02772
02773
02774
02775
02776
02777
02778
02779
02780
02781
02782
02783
02784
02785
02786
02787
02788
02789
02790 void QCAD::CISolver::fill1Pmx(const Teuchos::RCP<Albany::EigendataStruct>& eigenData1P)
02791 {
02792 const double IMAG_TOL = 1e-8;
02793
02794
02795 for(int i=0; i<n1PperBlock; i++) {
02796 if(eigenData1P->eigenvalueIm != Teuchos::null)
02797 assert( fabs((*(eigenData1P->eigenvalueIm))[i]) < IMAG_TOL );
02798
02799 blockU->el(i,i) = -(*(eigenData1P->eigenvalueRe))[i];
02800 blockD->el(i,i) = -(*(eigenData1P->eigenvalueRe))[i];
02801 *out << "DEBUG CI 1P Block El (" <<i<<","<<i<<") = " << -(*(eigenData1P->eigenvalueRe))[i] << std::endl;
02802
02803 for(int j=i+1; j<n1PperBlock; j++) {
02804 blockU->el(i,j) = 0; blockU->el(j,i) = 0;
02805 blockD->el(i,j) = 0; blockD->el(j,i) = 0;
02806 }
02807 }
02808
02809 mx1P = Teuchos::rcp(new AlbanyCI::BlockTensor<AlbanyCI::dcmplx>(basis1P, blocks1P, 1));
02810
02811 }
02812
02813
02814
02815 void QCAD::CISolver::fill1Pmx(const Teuchos::RCP<Albany::EigendataStruct>& eigenData1P,
02816 const Teuchos::RCP<Epetra_Vector>& g_noCharge,
02817 const Teuchos::RCP<Epetra_Vector>& g_delta,
02818 double deltaScale, bool bRealEvecs, bool bVerbose)
02819 {
02820 const double IMAG_TOL = 1e-8;
02821
02822
02823 int rIndx = 0;
02824 int rIndxInc = bRealEvecs ? 1 : 2;
02825 for(int i=0; i < n1PperBlock; i++) {
02826 assert(rIndx < g_delta->MyLength());
02827
02828 if(eigenData1P->eigenvalueIm != Teuchos::null)
02829 assert( fabs((*(eigenData1P->eigenvalueIm))[i]) < IMAG_TOL );
02830
02831 double delta_re = -( (*g_delta)[rIndx] - (*g_noCharge)[rIndx] );
02832 double delta_im = bRealEvecs ? 0 : -( (*g_delta)[rIndx+1] - (*g_noCharge)[rIndx+1] );
02833 delta_re *= deltaScale; delta_im *= deltaScale;
02834
02835 blockU->el(i,i) = -(*(eigenData1P->eigenvalueRe))[i] - delta_re;
02836 blockD->el(i,i) = -(*(eigenData1P->eigenvalueRe))[i] - delta_re;
02837 *out << "DEBUG CI 1P Block El (" <<i<<","<<i<<") = " << blockU->el(i,i) << "[no imag] = "
02838 << -(*(eigenData1P->eigenvalueRe))[i] << " - " << "(" << delta_re << " + i*" << delta_im << ")" << std::endl;
02839 rIndx += rIndxInc;
02840
02841 for(int j=i+1; j < n1PperBlock; j++) {
02842 assert(rIndx < g_delta->MyLength());
02843 delta_re = -((*g_delta)[rIndx] - (*g_noCharge)[rIndx]);
02844 delta_im = bRealEvecs ? 0 : -((*g_delta)[rIndx+1] - (*g_noCharge)[rIndx+1]);
02845 blockU->el(i,j) = -delta_re; blockU->el(j,i) = -delta_re;
02846 blockD->el(i,j) = -delta_re; blockD->el(j,i) = -delta_re;
02847 *out << "DEBUG CI 1P Block El (" <<i<<","<<j<<") = - (" << delta_re << " + i*" << delta_im << ") [no imag]" << std::endl;
02848 rIndx += rIndxInc;
02849 }
02850 }
02851
02852 mx1P = Teuchos::rcp(new AlbanyCI::BlockTensor<AlbanyCI::dcmplx>(basis1P, blocks1P, 1));
02853
02854 }
02855
02856
02857 void QCAD::CISolver::fill2Pmx(Teuchos::RCP<Albany::EigendataStruct> eigenData1P,
02858 const SolverSubSolver* coulombSolver,
02859 const SolverSubSolver* coulombSolver_ImPart,
02860 const Teuchos::RCP<Epetra_Vector>& g_noCharge,
02861 bool bRealEvecs, bool bVerbose)
02862 {
02863 Teuchos::RCP<Albany::EigendataStruct> eigenDataNull = Teuchos::null;
02864 Teuchos::RCP<Epetra_Vector> g_reSrc, g_imSrc;
02865
02866
02867 for(int i2=0; i2<n1PperBlock; i2++) {
02868 for(int i4=i2; i4<n1PperBlock; i4++) {
02869
02870
02871 if(bVerbose) *out << "QCAD Solve: Coulomb " << i2 << "," << i4 << " Poisson" << std::endl;
02872 SetCoulombParams( coulombSolver->params_in, i2,i4 );
02873 QCAD::SolveModel(*coulombSolver, eigenData1P, eigenDataNull);
02874 g_reSrc = coulombSolver->responses_out->get_g(0);
02875
02876 *out << "DEBUG: g_reSrc vector:" << std::endl;
02877 for(int i=0; i< g_reSrc->MyLength(); i++) *out << " g_reSrc[" << i << "] = " << (*g_reSrc)[i] << std::endl;
02878
02879
02880 if(!bRealEvecs) {
02881
02882 if(bVerbose) *out << "QCAD Solve: Imaginary Coulomb " << i2 << "," << i4 << " Poisson" << std::endl;
02883 SetCoulombParams( coulombSolver_ImPart->params_in, i2,i4 );
02884 QCAD::SolveModel(*coulombSolver_ImPart, eigenData1P, eigenDataNull);
02885 g_imSrc = coulombSolver_ImPart->responses_out->get_g(0);
02886
02887 *out << "DEBUG: g_imSrc vector:" << std::endl;
02888 for(int i=0; i< g_imSrc->MyLength(); i++) *out << " g_imSrc[" << i << "] = " << (*g_imSrc)[i] << std::endl;
02889 }
02890
02891 if(g_noCharge != Teuchos::null) {
02892 *out << "DEBUG: g_noCharge vector:" << std::endl;
02893 for(int i=0; i< g_noCharge->MyLength(); i++) *out << " g_noCharge[" << i << "] = " << (*g_noCharge)[i] << std::endl;
02894 }
02895
02896 int rIndx = 0 ;
02897
02898 if(!bRealEvecs) {
02899 for(int i1=0; i1<n1PperBlock; i1++) {
02900 for(int i3=i1; i3<n1PperBlock; i3++) {
02901 assert(rIndx < g_reSrc->MyLength());
02902 double c_reSrc_re = -(*g_reSrc)[rIndx];
02903 double c_reSrc_im = -(*g_reSrc)[rIndx+1];
02904 double c_imSrc_re = -(*g_imSrc)[rIndx];
02905 double c_imSrc_im = -(*g_imSrc)[rIndx+1];
02906
02907 if(g_noCharge != Teuchos::null) {
02908
02909 c_reSrc_re += (*g_noCharge)[rIndx];
02910 c_reSrc_im += (*g_noCharge)[rIndx+1];
02911 c_imSrc_re += (*g_noCharge)[rIndx];
02912 c_imSrc_im += (*g_noCharge)[rIndx+1];
02913 }
02914
02915
02916 double c_re = c_reSrc_re - c_imSrc_im;
02917 double c_im = c_reSrc_im + c_imSrc_re;
02918
02919 *out << "DEBUG CI 2P Block El (" <<i1<<","<<i2<<","<<i3<<","<<i4<<") = " << c_re << " + i*" << c_im << std::endl;
02920
02921
02922
02923 blockUU->el(i1,i2,i3,i4) = c_re;
02924 blockUU->el(i3,i2,i1,i4) = c_re;
02925 blockUU->el(i1,i4,i3,i2) = c_re;
02926 blockUU->el(i3,i4,i1,i2) = c_re;
02927
02928 blockUD->el(i1,i2,i3,i4) = c_re;
02929 blockUD->el(i3,i2,i1,i4) = c_re;
02930 blockUD->el(i1,i4,i3,i2) = c_re;
02931 blockUD->el(i3,i4,i1,i2) = c_re;
02932
02933 blockDU->el(i1,i2,i3,i4) = c_re;
02934 blockDU->el(i3,i2,i1,i4) = c_re;
02935 blockDU->el(i1,i4,i3,i2) = c_re;
02936 blockDU->el(i3,i4,i1,i2) = c_re;
02937
02938 blockDD->el(i1,i2,i3,i4) = c_re;
02939 blockDD->el(i3,i2,i1,i4) = c_re;
02940 blockDD->el(i1,i4,i3,i2) = c_re;
02941 blockDD->el(i3,i4,i1,i2) = c_re;
02942
02943 rIndx += 2;
02944 }
02945 }
02946 }
02947 else {
02948 for(int i1=0; i1<n1PperBlock; i1++) {
02949 for(int i3=i1; i3<n1PperBlock; i3++) {
02950 assert(rIndx < g_reSrc->MyLength());
02951 double c_reSrc_re = -(*g_reSrc)[rIndx];
02952
02953 if(g_noCharge != Teuchos::null) c_reSrc_re += (*g_noCharge)[rIndx];
02954
02955
02956 double c_re = c_reSrc_re;
02957
02958 *out << "DEBUG CI 2P Block El (" <<i1<<","<<i2<<","<<i3<<","<<i4<<") = " << c_re << std::endl;
02959
02960
02961
02962 blockUU->el(i1,i2,i3,i4) = c_re;
02963 blockUU->el(i3,i2,i1,i4) = c_re;
02964 blockUU->el(i1,i4,i3,i2) = c_re;
02965 blockUU->el(i3,i4,i1,i2) = c_re;
02966
02967 blockUD->el(i1,i2,i3,i4) = c_re;
02968 blockUD->el(i3,i2,i1,i4) = c_re;
02969 blockUD->el(i1,i4,i3,i2) = c_re;
02970 blockUD->el(i3,i4,i1,i2) = c_re;
02971
02972 blockDU->el(i1,i2,i3,i4) = c_re;
02973 blockDU->el(i3,i2,i1,i4) = c_re;
02974 blockDU->el(i1,i4,i3,i2) = c_re;
02975 blockDU->el(i3,i4,i1,i2) = c_re;
02976
02977 blockDD->el(i1,i2,i3,i4) = c_re;
02978 blockDD->el(i3,i2,i1,i4) = c_re;
02979 blockDD->el(i1,i4,i3,i2) = c_re;
02980 blockDD->el(i3,i4,i1,i2) = c_re;
02981
02982 rIndx += 1;
02983 }
02984 }
02985 }
02986 }
02987 }
02988
02989 mx2P = Teuchos::rcp(new AlbanyCI::BlockTensor<AlbanyCI::dcmplx>(basis1P, blocks2P, 2));
02990
02991 }
02992
02993
02994 Teuchos::RCP<AlbanyCI::Solution>
02995 QCAD::CISolver::Solve(Teuchos::RCP<Teuchos::ParameterList> AlbanyCIList) const
02996 {
02997 AlbanyCI::Solver solver;
02998 return solver.solve(AlbanyCIList, mx1P, mx2P, comm, out);
02999 }
03000
03001
03002 Teuchos::RCP<Epetra_MultiVector>
03003 QCAD::CISolver::ComputeStateDensities(Teuchos::RCP<Albany::EigendataStruct> eigenData1P, Teuchos::RCP<AlbanyCI::Solution> soln)
03004 {
03005 std::vector<double> eigenvalues = soln->getEigenvalues();
03006 int nCIevals = eigenvalues.size();
03007 std::vector< std::vector< AlbanyCI::dcmplx > > mxPx;
03008 bool bComplex = (eigenData1P->eigenvectorIm != Teuchos::null);
03009
03010 Teuchos::RCP<Epetra_MultiVector> mbStateDensities =
03011 Teuchos::rcp( new Epetra_MultiVector(eigenData1P->eigenvectorRe->Map(), nCIevals, true ));
03012
03013 for(int k=0; k < nCIevals; k++) {
03014 soln->getEigenvectorPxMatrix(k, mxPx);
03015
03016
03017
03018
03019
03020 if(bComplex) {
03021 for(int i=0; i < 2*n1PperBlock; i++) {
03022 const Epetra_Vector& vi_real = *((*(eigenData1P->eigenvectorRe))(i % n1PperBlock));
03023 const Epetra_Vector& vi_imag = *((*(eigenData1P->eigenvectorIm))(i % n1PperBlock));
03024
03025 for(int j=0; j < 2*n1PperBlock; j++) {
03026 const Epetra_Vector& vj_real = *((*(eigenData1P->eigenvectorRe))(j % n1PperBlock));
03027 const Epetra_Vector& vj_imag = *((*(eigenData1P->eigenvectorIm))(j % n1PperBlock));
03028
03029
03030 (*mbStateDensities)(k)->Multiply( mxPx[i][j], vi_real, vj_real, 1.0);
03031 (*mbStateDensities)(k)->Multiply( mxPx[i][j], vi_imag, vj_imag, 1.0);
03032 }
03033 }
03034 }
03035 else {
03036 for(int i=0; i < 2*n1PperBlock; i++) {
03037 const Epetra_Vector& vi_real = *((*(eigenData1P->eigenvectorRe))(i % n1PperBlock));
03038
03039 for(int j=0; j < 2*n1PperBlock; j++) {
03040 const Epetra_Vector& vj_real = *((*(eigenData1P->eigenvectorRe))(j % n1PperBlock));
03041 (*mbStateDensities)(k)->Multiply( mxPx[i][j], vi_real, vj_real, 1.0);
03042 }
03043 }
03044 }
03045 }
03046 return mbStateDensities;
03047 }
03048
03049
03050 void QCAD::CISolver::SetCoulombParams(const Teuchos::RCP<EpetraExt::ModelEvaluator::InArgs> inArgs, int i2, int i4) const
03051 {
03052 TEUCHOS_TEST_FOR_EXCEPTION( inArgs->Np() < 1, Teuchos::Exceptions::InvalidParameter,
03053 "Cannot set coulomb parameters because there are no parameter vectors.");
03054 Teuchos::RCP<const Epetra_Vector> p_ro = inArgs->get_p(0);
03055 Teuchos::RCP<Epetra_Vector> p = Teuchos::rcp( new Epetra_Vector( *p_ro ) );
03056
03057
03058 std::size_t nParams = p->GlobalLength();
03059 (*p)[ nParams-2 ] = (double) i2;
03060 (*p)[ nParams-1 ] = (double) i4;
03061
03062 inArgs->set_p(0, p);
03063 }
03064
03065 #endif // ALBANY_CI
03066
03067
03068
03069
03070
03071 void QCAD::SetPreviousDensityMixing(const Teuchos::RCP<EpetraExt::ModelEvaluator::InArgs> inArgs, double mixingFactor)
03072 {
03073 TEUCHOS_TEST_FOR_EXCEPTION( inArgs->Np() < 1, Teuchos::Exceptions::InvalidParameter,
03074 "Cannot set previous density mixing because there are no parameter vectors.");
03075 Teuchos::RCP<const Epetra_Vector> p_ro = inArgs->get_p(0);
03076 Teuchos::RCP<Epetra_Vector> p = Teuchos::rcp( new Epetra_Vector( *p_ro ) );
03077
03078
03079 std::size_t nParams = p->GlobalLength();
03080 (*p)[ nParams-1 ] = mixingFactor;
03081 inArgs->set_p(0, p);
03082 }
03083
03084 void QCAD::SolveModel(const QCAD::SolverSubSolver& ss)
03085 {
03086 ss.model->evalModel( (*ss.params_in), (*ss.responses_out) );
03087 }
03088
03089 void QCAD::SolveModel(const QCAD::SolverSubSolver& ss,
03090 Albany::StateArrays*& pInitialStates, Albany::StateArrays*& pFinalStates)
03091 {
03092 if(pInitialStates != NULL)
03093 ss.app->getStateMgr().importStateData( *pInitialStates );
03094
03095 ss.model->evalModel( (*ss.params_in), (*ss.responses_out) );
03096
03097 pFinalStates = &(ss.app->getStateMgr().getStateArrays());
03098 }
03099
03100 void QCAD::SolveModel(const QCAD::SolverSubSolver& ss,
03101 Teuchos::RCP<Albany::EigendataStruct>& pInitialEData,
03102 Teuchos::RCP<Albany::EigendataStruct>& pFinalEData)
03103 {
03104 if(pInitialEData != Teuchos::null)
03105 ss.app->getStateMgr().setEigenData(pInitialEData);
03106
03107 ss.model->evalModel( (*ss.params_in), (*ss.responses_out) );
03108
03109 pFinalEData = ss.app->getStateMgr().getEigenData();
03110 }
03111
03112
03113 void QCAD::SolveModel(const QCAD::SolverSubSolver& ss,
03114 Albany::StateArrays*& pInitialStates, Albany::StateArrays*& pFinalStates,
03115 Teuchos::RCP<Albany::EigendataStruct>& pInitialEData,
03116 Teuchos::RCP<Albany::EigendataStruct>& pFinalEData)
03117 {
03118 if(pInitialStates != NULL)
03119 ss.app->getStateMgr().importStateData( *pInitialStates );
03120
03121 if(pInitialEData != Teuchos::null)
03122 ss.app->getStateMgr().setEigenData(pInitialEData);
03123
03124 ss.model->evalModel( (*ss.params_in), (*ss.responses_out) );
03125
03126 pFinalStates = &(ss.app->getStateMgr().getStateArrays());
03127 pFinalEData = ss.app->getStateMgr().getEigenData();
03128 }
03129
03130
03131 void QCAD::CopyStateToContainer(Albany::StateArrays& state_arrays,
03132 std::string stateNameToCopy,
03133 std::vector<Intrepid::FieldContainer<RealType> >& dest)
03134 {
03135 Albany::StateArrayVec& src = state_arrays.elemStateArrays;
03136 int numWorksets = src.size();
03137 std::vector<int> dims;
03138
03139
03140 if(dest.size() != (unsigned int)numWorksets) {
03141 dest.resize(numWorksets);
03142 for (int ws = 0; ws < numWorksets; ws++) {
03143 src[ws][stateNameToCopy].dimensions(dims);
03144 dest[ws].resize(dims);
03145 }
03146 }
03147
03148 for (int ws = 0; ws < numWorksets; ws++)
03149 {
03150 src[ws][stateNameToCopy].dimensions(dims);
03151 TEUCHOS_TEST_FOR_EXCEPT( dims.size() != 2 );
03152
03153 for(int cell=0; cell < dims[0]; cell++)
03154 for(int qp=0; qp < dims[1]; qp++)
03155 dest[ws](cell,qp) = src[ws][stateNameToCopy](cell,qp);
03156 }
03157 }
03158
03159
03160
03161 void QCAD::CopyContainerToState(std::vector<Intrepid::FieldContainer<RealType> >& src,
03162 Albany::StateArrays& state_arrays,
03163 std::string stateNameOfCopy)
03164 {
03165 int numWorksets = src.size();
03166 Albany::StateArrayVec& dest = state_arrays.elemStateArrays;
03167 std::vector<int> dims;
03168
03169 for (int ws = 0; ws < numWorksets; ws++)
03170 {
03171 dest[ws][stateNameOfCopy].dimensions(dims);
03172 TEUCHOS_TEST_FOR_EXCEPT( dims.size() != 2 );
03173
03174 for(int cell=0; cell < dims[0]; cell++) {
03175 for(int qp=0; qp < dims[1]; qp++) {
03176 TEUCHOS_TEST_FOR_EXCEPT( std::isnan(src[ws](cell,qp)) );
03177 dest[ws][stateNameOfCopy](cell,qp) = src[ws](cell,qp);
03178 }
03179 }
03180 }
03181 }
03182
03183
03184 void QCAD::CopyContainer(std::vector<Intrepid::FieldContainer<RealType> >& src,
03185 std::vector<Intrepid::FieldContainer<RealType> >& dest)
03186 {
03187 int numWorksets = src.size();
03188
03189 if(dest.size() != (unsigned int)numWorksets)
03190 dest.resize(numWorksets);
03191
03192 for (int ws = 0; ws < numWorksets; ws++)
03193 {
03194 dest[ws] = src[ws];
03195 }
03196 }
03197
03198
03199 void QCAD::AddContainerToContainer(std::vector<Intrepid::FieldContainer<RealType> >& src,
03200 std::vector<Intrepid::FieldContainer<RealType> >& dest,
03201 double srcFactor, double thisFactor)
03202 {
03203 int numWorksets = src.size();
03204 std::vector<int> dims;
03205
03206 for (int ws = 0; ws < numWorksets; ws++)
03207 {
03208 dest[ws].dimensions(dims);
03209 TEUCHOS_TEST_FOR_EXCEPT( dims.size() != 2 );
03210
03211 for(int cell=0; cell < dims[0]; cell++) {
03212 for(int qp=0; qp < dims[1]; qp++) {
03213 TEUCHOS_TEST_FOR_EXCEPT( std::isnan(src[ws](cell,qp)) );
03214 dest[ws](cell,qp) = thisFactor * dest[ws](cell,qp) + srcFactor * src[ws](cell,qp);
03215 }
03216 }
03217 }
03218 }
03219
03220
03221
03222
03223
03224 void QCAD::AddContainerToState(std::vector<Intrepid::FieldContainer<RealType> >& src,
03225 Albany::StateArrays& state_arrays,
03226 std::string stateName, double srcFactor, double thisFactor)
03227 {
03228 int numWorksets = src.size();
03229 Albany::StateArrayVec& dest = state_arrays.elemStateArrays;
03230 std::vector<int> dims;
03231
03232 for (int ws = 0; ws < numWorksets; ws++)
03233 {
03234 dest[ws][stateName].dimensions(dims);
03235 TEUCHOS_TEST_FOR_EXCEPT( dims.size() != 2 );
03236
03237 for(int cell=0; cell < dims[0]; cell++) {
03238 for(int qp=0; qp < dims[1]; qp++) {
03239 TEUCHOS_TEST_FOR_EXCEPT( std::isnan(src[ws](cell,qp)) );
03240 dest[ws][stateName](cell,qp) = thisFactor * dest[ws][stateName](cell,qp) + srcFactor * src[ws](cell,qp);
03241 }
03242 }
03243 }
03244 }
03245
03246
03247
03248
03249
03250 void QCAD::CopyState(Albany::StateArrays& state_arrays,
03251 Albany::StateArrays& dest_arrays,
03252 std::string stateNameToCopy)
03253 {
03254 Albany::StateArrayVec& src = state_arrays.elemStateArrays;
03255 Albany::StateArrayVec& dest = dest_arrays.elemStateArrays;
03256 int numWorksets = src.size();
03257 int totalSize;
03258
03259 for (int ws = 0; ws < numWorksets; ws++)
03260 {
03261 totalSize = src[ws][stateNameToCopy].size();
03262 for(int i=0; i<totalSize; ++i)
03263 dest[ws][stateNameToCopy][i] = src[ws][stateNameToCopy][i];
03264 }
03265 }
03266
03267
03268 void QCAD::AddStateToState(Albany::StateArrays& state_arrays,
03269 std::string srcStateNameToAdd,
03270 Albany::StateArrays& dest_arrays,
03271 std::string destStateNameToAddTo)
03272 {
03273 Albany::StateArrayVec& src = state_arrays.elemStateArrays;
03274 Albany::StateArrayVec& dest = dest_arrays.elemStateArrays;
03275 int totalSize, numWorksets = src.size();
03276 TEUCHOS_TEST_FOR_EXCEPT( numWorksets != (int)dest.size() );
03277
03278 for (int ws = 0; ws < numWorksets; ws++)
03279 {
03280 totalSize = src[ws][srcStateNameToAdd].size();
03281
03282 for(int i=0; i<totalSize; ++i)
03283 dest[ws][destStateNameToAddTo][i] += src[ws][srcStateNameToAdd][i];
03284 }
03285 }
03286
03287
03288 void QCAD::SubtractStateFromState(Albany::StateArrays& state_arrays,
03289 std::string srcStateNameToSubtract,
03290 Albany::StateArrays& dest_arrays,
03291 std::string destStateNameToSubtractFrom)
03292 {
03293 Albany::StateArrayVec& src = state_arrays.elemStateArrays;
03294 Albany::StateArrayVec& dest = dest_arrays.elemStateArrays;
03295 int totalSize, numWorksets = src.size();
03296 TEUCHOS_TEST_FOR_EXCEPT( numWorksets != (int)dest.size() );
03297
03298 for (int ws = 0; ws < numWorksets; ws++)
03299 {
03300 totalSize = src[ws][srcStateNameToSubtract].size();
03301
03302 for(int i=0; i<totalSize; ++i)
03303 dest[ws][destStateNameToSubtractFrom][i] -= src[ws][srcStateNameToSubtract][i];
03304 }
03305 }
03306
03307 double QCAD::getMaxDifference(Albany::StateArrays& state_arrays,
03308 std::vector<Intrepid::FieldContainer<RealType> >& prevState,
03309 std::string stateName)
03310 {
03311 double maxDiff = 0.0;
03312 Albany::StateArrayVec& states = state_arrays.elemStateArrays;
03313 int numWorksets = states.size();
03314 std::vector<int> dims;
03315
03316 TEUCHOS_TEST_FOR_EXCEPT( ! (numWorksets == (int)prevState.size()) );
03317
03318 for (int ws = 0; ws < numWorksets; ws++)
03319 {
03320 states[ws][stateName].dimensions(dims);
03321 TEUCHOS_TEST_FOR_EXCEPT( dims.size() != 2 );
03322
03323 for(int cell=0; cell < dims[0]; cell++)
03324 {
03325 for(int qp=0; qp < dims[1]; qp++)
03326 {
03327
03328
03329 if( fabs( states[ws][stateName](cell,qp) - prevState[ws](cell,qp) ) > maxDiff )
03330 maxDiff = fabs( states[ws][stateName](cell,qp) - prevState[ws](cell,qp) );
03331 }
03332 }
03333 }
03334 return maxDiff;
03335 }
03336
03337
03338 double QCAD::getNorm2Difference(Albany::StateArrays& state_arrays,
03339 std::vector<Intrepid::FieldContainer<RealType> >& prevState,
03340 std::string stateName)
03341 {
03342 double norm2 = 0.0;
03343 Albany::StateArrayVec& states = state_arrays.elemStateArrays;
03344 int numWorksets = states.size();
03345 std::vector<int> dims;
03346
03347 TEUCHOS_TEST_FOR_EXCEPT( ! (numWorksets == (int)prevState.size()) );
03348
03349 for (int ws = 0; ws < numWorksets; ws++)
03350 {
03351 states[ws][stateName].dimensions(dims);
03352 TEUCHOS_TEST_FOR_EXCEPT( dims.size() != 2 );
03353
03354 for(int cell=0; cell < dims[0]; cell++)
03355 {
03356 for(int qp=0; qp < dims[1]; qp++)
03357 {
03358 norm2 += pow( states[ws][stateName](cell,qp) - prevState[ws](cell,qp), 2);
03359 }
03360 }
03361 }
03362 return norm2;
03363 }
03364
03365
03366 double QCAD::getNorm2(std::vector<Intrepid::FieldContainer<RealType> >& container, const Teuchos::RCP<const Epetra_Comm>& comm)
03367 {
03368 double norm2 = 0.0;
03369 int numWorksets = container.size();
03370 std::vector<int> dims;
03371
03372 for (int ws = 0; ws < numWorksets; ws++)
03373 {
03374 container[ws].dimensions(dims);
03375 TEUCHOS_TEST_FOR_EXCEPT( dims.size() != 2 );
03376
03377 for(int cell=0; cell < dims[0]; cell++)
03378 {
03379 for(int qp=0; qp < dims[1]; qp++)
03380 {
03381 norm2 += pow( container[ws](cell,qp), 2);
03382 }
03383 }
03384 }
03385
03386 double global_norm2;
03387 comm->SumAll(&norm2, &global_norm2, 1);
03388 return global_norm2;
03389 }
03390
03391 int QCAD::getElementCount(std::vector<Intrepid::FieldContainer<RealType> >& container)
03392 {
03393 int cnt = 0;
03394 int numWorksets = container.size();
03395
03396 for (int ws = 0; ws < numWorksets; ws++)
03397 {
03398 cnt += container[ws].size();
03399 }
03400 return cnt;
03401 }
03402
03403
03404 void QCAD::ResetEigensolverShift(const Teuchos::RCP<EpetraExt::ModelEvaluator>& Solver, double newShift,
03405 Teuchos::RCP<Teuchos::ParameterList>& eigList)
03406 {
03407 Teuchos::RCP<Piro::Epetra::LOCASolver> pels = Teuchos::rcp_dynamic_cast<Piro::Epetra::LOCASolver>(Solver);
03408 TEUCHOS_TEST_FOR_EXCEPT(pels == Teuchos::null);
03409
03410 Teuchos::RCP<LOCA::Stepper> stepper = pels->getLOCAStepperNonConst();
03411 const Teuchos::ParameterList& oldEigList = stepper->getList()->sublist("LOCA").sublist(
03412 "Stepper").sublist("Eigensolver");
03413
03414 eigList = Teuchos::rcp(new Teuchos::ParameterList(oldEigList));
03415 eigList->set("Shift",newShift);
03416
03417
03418
03419 std::cout << "QCAD Solver setting eigensolver shift = "
03420 << std::setprecision(5) << newShift << std::endl;
03421
03422 stepper->eigensolverReset(eigList);
03423 }
03424
03425
03426 double QCAD::GetEigensolverShift(const QCAD::SolverSubSolver& ss, double pcBelowMinPotential)
03427 {
03428 int Ng = ss.responses_out->Ng();
03429 TEUCHOS_TEST_FOR_EXCEPT( Ng <= 0 );
03430
03431 Teuchos::RCP<Epetra_Vector> gVector = ss.responses_out->get_g(0);
03432
03433
03434
03435
03436 int minPotentialResponseIndex = gVector->GlobalLength() - 5;
03437 double minVal = (*gVector)[minPotentialResponseIndex];
03438
03439
03440
03441
03442
03443 double shift = -minVal*(1.0 + pcBelowMinPotential/100.0);
03444 return shift;
03445 }
03446
03447
03448
03449
03450
03451 std::vector<std::string> QCAD::string_split(const std::string& s, char delim, bool bProtect)
03452 {
03453 int last = 0;
03454 int parenLevel=0, bracketLevel=0, braceLevel=0;
03455
03456 std::vector<std::string> ret(1);
03457 for(std::size_t i=0; i<s.size(); i++) {
03458 if(s[i] == delim && parenLevel==0 && bracketLevel==0 && braceLevel==0) {
03459 ret.push_back("");
03460 last++;
03461 }
03462 else ret[last] += s[i];
03463
03464 if(bProtect) {
03465 if( s[i] == '(') parenLevel++;
03466 else if(s[i] == ')') parenLevel--;
03467 else if(s[i] == '[') bracketLevel++;
03468 else if(s[i] == ']') bracketLevel--;
03469 else if(s[i] == '{') braceLevel++;
03470 else if(s[i] == '}') braceLevel--;
03471 }
03472 }
03473 return ret;
03474 }
03475
03476 std::string QCAD::string_remove_whitespace(const std::string& s)
03477 {
03478 std::string ret;
03479 for(std::size_t i=0; i<s.size(); i++) {
03480 if(s[i] == ' ') continue;
03481 ret += s[i];
03482 }
03483 return ret;
03484 }
03485
03486
03487
03488 std::vector<std::string> QCAD::string_parse_function(const std::string& s)
03489 {
03490 std::vector<std::string> ret;
03491 std::string fnName, fnArgString;
03492 std::size_t firstOpenParen, lastCloseParen;
03493
03494 firstOpenParen = s.find_first_of('(');
03495 lastCloseParen = s.find_last_of(')');
03496
03497 if(firstOpenParen == std::string::npos || lastCloseParen == std::string::npos) {
03498 TEUCHOS_TEST_FOR_EXCEPTION(true, Teuchos::Exceptions::InvalidParameter,
03499 "Malformed function string: " << s << std::endl);
03500 }
03501
03502 fnName = s.substr(0,firstOpenParen);
03503 fnArgString = s.substr(firstOpenParen+1,lastCloseParen-firstOpenParen-1);
03504
03505 ret = QCAD::string_split(fnArgString,',',true);
03506 ret.insert(ret.begin(),fnName);
03507 return ret;
03508 }
03509
03510 std::map<std::string,std::string> QCAD::string_parse_arrayref(const std::string& s)
03511 {
03512 std::map<std::string,std::string> ret;
03513 std::string arName, indexString;
03514 std::size_t firstOpenBracket, lastCloseBracket;
03515
03516 firstOpenBracket = s.find_first_of('[');
03517 lastCloseBracket = s.find_last_of(']');
03518
03519 if(firstOpenBracket == std::string::npos || lastCloseBracket == std::string::npos) {
03520 TEUCHOS_TEST_FOR_EXCEPTION(true, Teuchos::Exceptions::InvalidParameter,
03521 "Malformed array string: " << s << std::endl);
03522 }
03523
03524 arName = s.substr(0,firstOpenBracket);
03525 indexString = s.substr(firstOpenBracket+1,lastCloseBracket-firstOpenBracket-1);
03526
03527 ret["name"] = arName;
03528 ret["index"] = indexString;
03529 return ret;
03530 }
03531
03532 std::vector<int> QCAD::string_expand_compoundindex(const std::string& indexStr, int min_index, int max_index)
03533 {
03534 std::vector<int> ret;
03535 std::vector<std::string> simpleRanges = QCAD::string_split(indexStr,',',true);
03536 std::vector<std::string>::const_iterator it;
03537
03538 for(it = simpleRanges.begin(); it != simpleRanges.end(); it++) {
03539 std::vector<std::string> endpts = QCAD::string_split( (*it), ':', true);
03540 if(endpts.size() == 1)
03541 ret.push_back( atoi(endpts[0].c_str()) );
03542 else if(endpts.size() == 2) {
03543 int a=min_index ,b=max_index;
03544 if(endpts[0] != "") a = atoi(endpts[0].c_str());
03545 if(endpts[1] != "") b = atoi(endpts[1].c_str());
03546
03547 TEUCHOS_TEST_FOR_EXCEPTION(a < min_index || a > max_index || b < min_index || b > max_index,
03548 Teuchos::Exceptions::InvalidParameter, "Index '"<< indexStr
03549 << "' is out of bounds (min="<<min_index<<", max="<<max_index<<")" << std::endl);
03550
03551 for(int i=a; i<b; i++) ret.push_back(i);
03552 }
03553 else TEUCHOS_TEST_FOR_EXCEPTION(true, Teuchos::Exceptions::InvalidParameter,
03554 "Malformed array index: " << indexStr << std::endl);
03555 }
03556 return ret;
03557 }
03558