00001
00002
00003
00004
00005
00006
00007 #include <fstream>
00008 #include "Teuchos_TestForException.hpp"
00009 #include "Phalanx_DataLayout.hpp"
00010 #include "Sacado_ParameterRegistration.hpp"
00011 #include "QCAD_StringFormulaEvaluator.hpp"
00012
00013 template<typename EvalT, typename Traits>
00014 QCAD::SchrodingerPotential<EvalT, Traits>::
00015 SchrodingerPotential(Teuchos::ParameterList& p,
00016 const Teuchos::RCP<Albany::Layouts>& dl) :
00017 coordVec(p.get<std::string>("QP Coordinate Vector Name"), dl->qp_gradient),
00018 psi(p.get<std::string>("QP Variable Name"), dl->qp_scalar),
00019 V(p.get<std::string>("QP Potential Name"), dl->qp_scalar)
00020 {
00021
00022 Teuchos::ParameterList* psList = p.get<Teuchos::ParameterList*>("Parameter List");
00023
00024 Teuchos::RCP<const Teuchos::ParameterList> reflist =
00025 this->getValidSchrodingerPotentialParameters();
00026 psList->validateParameters(*reflist,0);
00027
00028 std::vector<PHX::DataLayout::size_type> dims;
00029 dl->qp_gradient->dimensions(dims);
00030 numQPs = dims[1];
00031 numDims = dims[2];
00032
00033 energy_unit_in_eV = p.get<double>("Energy unit in eV");
00034 length_unit_in_m = p.get<double>("Length unit in m");
00035
00036 potentialType = psList->get("Type", "defaultType");
00037 E0 = psList->get("E0", 1.0);
00038 scalingFactor = psList->get("Scaling Factor", 1.0);
00039
00040
00041 stringFormula = psList->get("Formula", "0");
00042
00043
00044 barrEffMass = psList->get<double>("Barrier Effective Mass", 0.0);
00045 barrWidth = psList->get<double>("Barrier Width", 0.0);
00046 wellEffMass = psList->get<double>("Well Effective Mass", 0.0);
00047 wellWidth = psList->get<double>("Well Width", 0.0);
00048
00049 potentialStateName = psList->get<std::string>("State Name","Not Specified");
00050
00051
00052 Teuchos::RCP<ParamLib> paramLib =
00053 p.get< Teuchos::RCP<ParamLib> >("Parameter Library", Teuchos::null);
00054 new Sacado::ParameterRegistration<EvalT, SPL_Traits>(
00055 "Schrodinger Potential E0", this, paramLib);
00056 new Sacado::ParameterRegistration<EvalT, SPL_Traits> (
00057 "Schrodinger Potential Scaling Factor", this, paramLib);
00058
00059 this->addDependentField(psi);
00060 this->addDependentField(coordVec);
00061
00062 this->addEvaluatedField(V);
00063 this->setName("Schrodinger Potential"+PHX::TypeString<EvalT>::value);
00064 }
00065
00066
00067 template<typename EvalT, typename Traits>
00068 void QCAD::SchrodingerPotential<EvalT, Traits>::
00069 postRegistrationSetup(typename Traits::SetupData d,
00070 PHX::FieldManager<Traits>& fm)
00071 {
00072 this->utils.setFieldData(V,fm);
00073 this->utils.setFieldData(psi,fm);
00074 this->utils.setFieldData(coordVec,fm);
00075 }
00076
00077
00078 template<typename EvalT, typename Traits>
00079 void QCAD::SchrodingerPotential<EvalT, Traits>::
00080 evaluateFields(typename Traits::EvalData workset)
00081 {
00082
00083
00084 if (potentialType == "Parabolic")
00085 {
00086 for (std::size_t cell = 0; cell < workset.numCells; ++cell) {
00087 for (std::size_t qp = 0; qp < numQPs; ++qp) {
00088 V(cell, qp) = parabolicPotentialValue(numDims, &coordVec(cell,qp,0));
00089 }
00090 }
00091 }
00092
00093
00094 else if (potentialType == "Infinite Wall")
00095 {
00096 for (std::size_t cell = 0; cell < workset.numCells; ++cell)
00097 for (std::size_t qp = 0; qp < numQPs; ++qp)
00098 V(cell, qp) = 0.0;
00099 }
00100
00101
00102 else if (potentialType == "Finite Wall")
00103 {
00104 for (std::size_t cell = 0; cell < workset.numCells; ++cell)
00105 {
00106 for (std::size_t qp = 0; qp < numQPs; ++qp)
00107 V(cell, qp) = finiteWallPotential(numDims, &coordVec(cell,qp,0));
00108 }
00109 }
00110
00111
00112 else if (potentialType == "String Formula")
00113 {
00114 for (std::size_t cell = 0; cell < workset.numCells; ++cell)
00115 {
00116 for (std::size_t qp = 0; qp < numQPs; ++qp)
00117 V(cell, qp) = stringFormulaPotential(numDims, &coordVec(cell,qp,0));
00118 }
00119 }
00120
00121
00122
00123 else if (potentialType == "From State")
00124 {
00125 Albany::StateArray& states = *workset.stateArrayPtr;
00126 Albany::MDArray& potentialState = states[potentialStateName];
00127
00128 for (std::size_t cell=0; cell < workset.numCells; ++cell) {
00129 for (std::size_t qp=0; qp < numQPs; ++qp) {
00130 double d = potentialState(cell, qp);
00131 V(cell, qp) = d;
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141 }
00142 }
00143 }
00144
00145
00146 else
00147 {
00148 TEUCHOS_TEST_FOR_EXCEPT(true);
00149 }
00150 }
00151
00152
00153 template<typename EvalT,typename Traits>
00154 typename QCAD::SchrodingerPotential<EvalT,Traits>::ScalarT&
00155 QCAD::SchrodingerPotential<EvalT,Traits>::getValue(const std::string &n)
00156 {
00157 if(n == "Schrodinger Potential Scaling Factor") return scalingFactor;
00158 else if(n == "Schrodinger Potential E0") return E0;
00159 else TEUCHOS_TEST_FOR_EXCEPT(true); return E0;
00160 }
00161
00162
00163 template<typename EvalT,typename Traits>
00164 Teuchos::RCP<const Teuchos::ParameterList>
00165 QCAD::SchrodingerPotential<EvalT,Traits>::getValidSchrodingerPotentialParameters() const
00166 {
00167 Teuchos::RCP<Teuchos::ParameterList> validPL =
00168 rcp(new Teuchos::ParameterList("Valid Schrodinger Potential Params"));;
00169
00170 validPL->set<std::string>("Type", "defaultType", "Switch between different potential types");
00171 validPL->set<double>("E0", 1.0, "Energy scale - dependent on type");
00172 validPL->set<double>("Scaling Factor", 1.0, "Constant scaling factor");
00173
00174
00175 validPL->set<std::string>("Formula", "0", "Mathematical expression containing x,y,z that specifies the potential at coordinates (x,y,z). In 1D and 2D use just x and x,y respectively.");
00176
00177
00178 validPL->set<double>("Barrier Effective Mass", 0.0, "Barrier effective mass in [m0]");
00179 validPL->set<double>("Barrier Width", 0.0, "Barrier width in length_unit_in_m");
00180 validPL->set<double>("Well Effective Mass", 0.0, "Well effective mass in [m0]");
00181 validPL->set<double>("Well Width", 0.0, "Well width in length_unit_in_m");
00182
00183
00184
00185
00186
00187
00188 validPL->set<double>("Oxide Width", 0.0, "Oxide width in length_unit_in_m");
00189 validPL->set<double>("Silicon Width", 0.0, "Silicon width in length_unit_in_m");
00190
00191
00192 validPL->set<std::string>("State Name", "", "Name of state to import potential from");
00193
00194 return validPL;
00195 }
00196
00197
00198
00199
00200 template<typename EvalT,typename Traits>
00201 typename QCAD::SchrodingerPotential<EvalT,Traits>::ScalarT
00202 QCAD::SchrodingerPotential<EvalT,Traits>::parabolicPotentialValue(
00203 const int numDim, const MeshScalarT* coord)
00204 {
00205 ScalarT val;
00206 MeshScalarT r2;
00207 int i;
00208
00209
00210
00211
00212 const double hbar = 1.0546e-34;
00213 const double emass = 9.1094e-31;
00214 const double evPerJ = 6.2415e18;
00215
00216 const double parabolicFctr = 0.5 * (emass / (evPerJ * hbar*hbar) );
00217
00218
00219 ScalarT prefactor;
00220
00221 prefactor = parabolicFctr * E0*E0 * (energy_unit_in_eV * pow(length_unit_in_m,2));
00222 for(i=0, r2=0.0; i<numDim; i++)
00223 r2 += (coord[i]-0.5)*(coord[i]-0.5);
00224 val = prefactor * r2;
00225
00226 return scalingFactor * val;
00227 }
00228
00229
00230
00231
00232 template<typename EvalT,typename Traits>
00233 typename QCAD::SchrodingerPotential<EvalT,Traits>::ScalarT
00234 QCAD::SchrodingerPotential<EvalT,Traits>::finiteWallPotential(
00235 const int numDim, const MeshScalarT* coord)
00236 {
00237 ScalarT val;
00238
00239 switch (numDim)
00240 {
00241 case 1:
00242 {
00243 if ( (coord[0] >= 0) && (coord[0] < barrWidth) )
00244 val = E0;
00245 else if ( (coord[0] >= barrWidth) && (coord[0] <= (barrWidth+wellWidth)) )
00246 val = 0;
00247 else if ( (coord[0] > (barrWidth+wellWidth)) && (coord[0] <= (2*barrWidth+wellWidth)) )
00248 val = E0;
00249 else
00250 TEUCHOS_TEST_FOR_EXCEPTION (true, Teuchos::Exceptions::InvalidParameter, std::endl
00251 << "Error! x coordinate is outside [0, 2*barrWidth+wellWidth] range,"
00252 << " make sure 1D Scale in Discretization equal to 2*barrWidth+wellWidth !" << std::endl);
00253 break;
00254 }
00255
00256 case 2:
00257 {
00258 if ( (coord[0] >= barrWidth) && (coord[0] <= (barrWidth+wellWidth)) &&
00259 (coord[1] >= barrWidth) && (coord[1] <= (barrWidth+wellWidth)) )
00260 val = 0.0;
00261 else
00262 val = E0;
00263 break;
00264 }
00265
00266 case 3:
00267 {
00268 if ( (coord[0] >= barrWidth) && (coord[0] <= (barrWidth+wellWidth)) &&
00269 (coord[1] >= barrWidth) && (coord[1] <= (barrWidth+wellWidth)) &&
00270 (coord[2] >= barrWidth) && (coord[2] <= (barrWidth+wellWidth)) )
00271 val = 0.0;
00272 else
00273 val = E0;
00274 break;
00275 }
00276
00277 default:
00278 {
00279 TEUCHOS_TEST_FOR_EXCEPTION (true, Teuchos::Exceptions::InvalidParameter, std::endl
00280 << "Error! Invalid numDim = " << numDim << ", must be 1 or 2 or 3 !" << std::endl);
00281 break;
00282 }
00283
00284 }
00285
00286 return scalingFactor * val;
00287 }
00288
00289
00290
00291
00292
00293 template<typename EvalT,typename Traits>
00294 typename QCAD::SchrodingerPotential<EvalT,Traits>::ScalarT
00295 QCAD::SchrodingerPotential<EvalT,Traits>::stringFormulaPotential(
00296 const int numDim, const MeshScalarT* coord)
00297 {
00298 ScalarT val;
00299 MeshScalarT x, y, z, result;
00300
00301 switch (numDim)
00302 {
00303 case 1:
00304 {
00305 x = coord[0];
00306 y = 0; z=0;
00307 break;
00308 }
00309
00310 case 2:
00311 {
00312 x = coord[0];
00313 y = coord[1];
00314 z = 0;
00315 break;
00316 }
00317
00318 case 3:
00319 {
00320 x = coord[0];
00321 y = coord[1];
00322 z = coord[2];
00323 break;
00324 }
00325
00326 default:
00327 {
00328 TEUCHOS_TEST_FOR_EXCEPTION (true, Teuchos::Exceptions::InvalidParameter, std::endl
00329 << "Error! Invalid numDim = " << numDim << ", must be 1 or 2 or 3 !" << std::endl);
00330 break;
00331 }
00332 }
00333
00334 result = Evaluate(stringFormula,x,y,z);
00335 val = result;
00336 return scalingFactor * val;
00337 }
00338
00339
00340
00341