00001
00002
00003
00004
00005
00006 #include <Teuchos_Array.hpp>
00007 #include <Epetra_LocalMap.h>
00008 #include "Albany_Utils.hpp"
00009 #include "QCAD_SaddleValueResponseFunction.hpp"
00010 #include "QCAD_GreensFunctionTunneling.hpp"
00011 #include <fstream>
00012
00014 namespace QCAD
00015 {
00016 bool ptInPolygon(const std::vector<QCAD::mathVector>& polygon, const QCAD::mathVector& pt);
00017 bool ptInPolygon(const std::vector<QCAD::mathVector>& polygon, const double* pt);
00018
00019 void gatherVector(std::vector<double>& v, std::vector<double>& gv,
00020 const Epetra_Comm& comm_);
00021 void getOrdering(const std::vector<double>& v, std::vector<int>& ordering);
00022 bool lessOp(std::pair<std::size_t, double> const& a,
00023 std::pair<std::size_t, double> const& b);
00024 double averageOfVector(const std::vector<double>& v);
00025 double distance(const std::vector<double>* vCoords, int ind1, int ind2, std::size_t nDims);
00026 }
00027
00028 QCAD::SaddleValueResponseFunction::
00029 SaddleValueResponseFunction(
00030 const Teuchos::RCP<Albany::Application>& application,
00031 const Teuchos::RCP<Albany::AbstractProblem>& problem,
00032 const Teuchos::RCP<Albany::MeshSpecsStruct>& ms,
00033 const Teuchos::RCP<Albany::StateManager>& stateMgr,
00034 Teuchos::ParameterList& params) :
00035 Albany::FieldManagerScalarResponseFunction(application, problem, ms, stateMgr),
00036 numDims(problem->spatialDimension()),
00037 comm(application->getComm() )
00038 {
00039 TEUCHOS_TEST_FOR_EXCEPTION (numDims < 2 || numDims > 3, Teuchos::Exceptions::InvalidParameter, std::endl
00040 << "Saddle Point not implemented for " << numDims << " dimensions." << std::endl);
00041
00042 params.set("Response Function", Teuchos::rcp(this,false));
00043
00044 Teuchos::Array<double> ar;
00045
00046 imagePtSize = params.get<double>("Image Point Size", 0.01);
00047 nImagePts = params.get<int>("Number of Image Points", 10);
00048 maxTimeStep = params.get<double>("Max Time Step", 1.0);
00049 minTimeStep = params.get<double>("Min Time Step", 0.002);
00050 maxIterations = params.get<int>("Maximum Iterations", 100);
00051 backtraceAfterIters = params.get<int>("Backtrace After Iteration", 10000000);
00052 convergeTolerance = params.get<double>("Convergence Tolerance", 1e-5);
00053 minSpringConstant = params.get<double>("Min Spring Constant", 1.0);
00054 maxSpringConstant = params.get<double>("Max Spring Constant", 1.0);
00055 outputFilename = params.get<std::string>("Output Filename", "");
00056 debugFilename = params.get<std::string>("Debug Filename", "");
00057 appendOutput = params.get<bool>("Append Output", false);
00058 nEvery = params.get<int>("Output Interval", 0);
00059 bClimbing = params.get<bool>("Climbing NEB", true);
00060 antiKinkFactor = params.get<double>("Anti-Kink Factor", 0.0);
00061 bAggregateWorksets = params.get<bool>("Aggregate Worksets", false);
00062 bAdaptivePointSize = params.get<bool>("Adaptive Image Point Size", false);
00063 minAdaptivePointWt = params.get<double>("Adaptive Min Point Weight", 5);
00064 maxAdaptivePointWt = params.get<double>("Adaptive Max Point Weight", 10);
00065 shortenBeginPc = params.get<double>("Percent to Shorten Begin", 0);
00066 shortenEndPc = params.get<double>("Percent to Shorten End", 0);
00067
00068 fieldCutoffFctr = params.get<double>("Levelset Field Cutoff Factor", 1.0);
00069 minPoolDepthFctr = params.get<double>("Levelset Minimum Pool Depth Factor", 1.0);
00070 distanceCutoffFctr = params.get<double>("Levelset Distance Cutoff Factor", 1.0);
00071 levelSetRadius = params.get<double>("Levelset Radius", 0);
00072
00073
00074 maxFinalPts = params.get<int>("Maximum Number of Final Points", nImagePts);
00075 gfGridSpacing = params.get<double>("GF-CBR Method Grid Spacing", 0.0005);
00076 fieldScaling = params.get<double>("Field Scaling Factor", 1.0);
00077
00078
00079 bSweepVds = params.get<bool>("GF-CBR Method Vds Sweep", false);
00080 initVds = params.get<double>("GF-CBR Method Vds Initial Value", 0.0);
00081 finalVds = params.get<double>("GF-CBR Method Vds Final Value", 0.0);
00082 stepsVds = params.get<int>("GF-CBR Method Vds Steps", 0);
00083
00084
00085 gfEigensolver = params.get<std::string>("GF-CBR Method Eigensolver", "tql2");
00086 std::cout << "gfEigensolver = " << gfEigensolver << std::endl;
00087
00088 bGetCurrent = (params.get<std::string>("Return Field Name", "") == "current");
00089
00090
00091 current_Ecutoff_offset_from_Emax = params.get<double>("GF-CBR Method Energy Cutoff Offset", 0.5);
00092
00093 if(backtraceAfterIters < 0) backtraceAfterIters = 10000000;
00094 else if(backtraceAfterIters <= 1) backtraceAfterIters = 2;
00095
00096 bLockToPlane = false;
00097 if(params.isParameter("Lock to z-coord")) {
00098 bLockToPlane = true;
00099 lockedZ = params.get<double>("Lock to z-coord");
00100 }
00101
00102 iSaddlePt = -1;
00103 returnFieldVal = -1.0;
00104
00105
00106 if(params.isParameter("Begin Point")) {
00107 beginRegionType = "Point";
00108 ar = params.get<Teuchos::Array<double> >("Begin Point");
00109 TEUCHOS_TEST_FOR_EXCEPTION (ar.size() != (int)numDims, Teuchos::Exceptions::InvalidParameter, std::endl
00110 << "Begin Point does not have " << numDims << " elements" << std::endl);
00111 beginPolygon.resize(1); beginPolygon[0].resize(numDims);
00112 for(std::size_t i=0; i<numDims; i++) beginPolygon[0][i] = ar[i];
00113 }
00114 else if(params.isParameter("Begin Element Block")) {
00115 beginRegionType = "Element Block";
00116 beginElementBlock = params.get<std::string>("Begin Element Block");
00117 }
00118 else if(params.isSublist("Begin Polygon")) {
00119 beginRegionType = "Polygon";
00120
00121 Teuchos::ParameterList& polyList = params.sublist("Begin Polygon");
00122 int nPts = polyList.get<int>("Number of Points");
00123 beginPolygon.resize(nPts);
00124
00125 for(int i=0; i<nPts; i++) {
00126 beginPolygon[i].resize(numDims);
00127 ar = polyList.get<Teuchos::Array<double> >( Albany::strint("Point",i) );
00128 TEUCHOS_TEST_FOR_EXCEPTION (ar.size() != (int)numDims, Teuchos::Exceptions::InvalidParameter, std::endl
00129 << "Begin polygon point does not have " << numDims << " elements" << std::endl);
00130 for(std::size_t k=0; k<numDims; k++) beginPolygon[i][k] = ar[k];
00131 }
00132 }
00133 else TEUCHOS_TEST_FOR_EXCEPTION (true, Teuchos::Exceptions::InvalidParameter, std::endl
00134 << "No beginning region specified for saddle pt" << std::endl);
00135
00136
00137
00138
00139 if(params.isParameter("End Point")) {
00140 endRegionType = "Point";
00141 ar = params.get<Teuchos::Array<double> >("End Point");
00142 TEUCHOS_TEST_FOR_EXCEPTION (ar.size() != (int)numDims, Teuchos::Exceptions::InvalidParameter, std::endl
00143 << "End Point does not have " << numDims << " elements" << std::endl);
00144 endPolygon.resize(1); endPolygon[0].resize(numDims);
00145 for(std::size_t i=0; i<numDims; i++) endPolygon[0][i] = ar[i];
00146 }
00147 else if(params.isParameter("End Element Block")) {
00148 endRegionType = "Element Block";
00149 endElementBlock = params.get<std::string>("End Element Block");
00150 }
00151 else if(params.isSublist("End Polygon")) {
00152 endRegionType = "Polygon";
00153
00154 Teuchos::ParameterList& polyList = params.sublist("End Polygon");
00155 int nPts = polyList.get<int>("Number of Points");
00156 endPolygon.resize(nPts);
00157
00158 for(int i=0; i<nPts; i++) {
00159 endPolygon[i].resize(numDims);
00160 ar = polyList.get<Teuchos::Array<double> >( Albany::strint("Point",i) );
00161 TEUCHOS_TEST_FOR_EXCEPTION (ar.size() != (int)numDims, Teuchos::Exceptions::InvalidParameter, std::endl
00162 << "End polygon point does not have " << numDims << " elements" << std::endl);
00163 for(std::size_t k=0; k<numDims; k++) endPolygon[i][k] = ar[k];
00164 }
00165 }
00166 else TEUCHOS_TEST_FOR_EXCEPTION (true, Teuchos::Exceptions::InvalidParameter, std::endl
00167 << "No ending region specified for saddle pt" << std::endl);
00168
00169
00170
00171 saddleGuessGiven = false;
00172 if(params.isParameter("Saddle Point Guess")) {
00173 saddleGuessGiven = true;
00174 ar = params.get<Teuchos::Array<double> >("Saddle Point Guess");
00175 TEUCHOS_TEST_FOR_EXCEPTION (ar.size() != (int)numDims, Teuchos::Exceptions::InvalidParameter, std::endl
00176 << "Saddle point guess does not have " << numDims << " elements" << std::endl);
00177 saddlePointGuess.resize(numDims);
00178 for(std::size_t i=0; i<numDims; i++) saddlePointGuess[i] = ar[i];
00179 }
00180
00181 debugMode = params.get<int>("Debug Mode",0);
00182
00183 imagePts.resize(nImagePts);
00184 imagePtValues.resize(nImagePts);
00185 imagePtWeights.resize(nImagePts);
00186 imagePtGradComps.resize(nImagePts*numDims);
00187
00188
00189
00190 if(numDims > 2) {
00191 zmin = params.get<double>("z min");
00192 zmax = params.get<double>("z max");
00193 }
00194
00195 this->setup(params);
00196 this->num_responses = 5;
00197 }
00198
00199 QCAD::SaddleValueResponseFunction::
00200 ~SaddleValueResponseFunction()
00201 {
00202 }
00203
00204 unsigned int
00205 QCAD::SaddleValueResponseFunction::
00206 numResponses() const
00207 {
00208 return this->num_responses;
00209 }
00210
00211 void
00212 QCAD::SaddleValueResponseFunction::
00213 evaluateResponse(const double current_time,
00214 const Epetra_Vector* xdot,
00215 const Epetra_Vector* xdotdot,
00216 const Epetra_Vector& x,
00217 const Teuchos::Array<ParamVec>& p,
00218 Epetra_Vector& g)
00219 {
00220 int dbMode = (comm->MyPID() == 0) ? debugMode : 0;
00221 if(comm->MyPID() != 0) outputFilename = "";
00222 if(comm->MyPID() != 0) debugFilename = "";
00223
00224 TEUCHOS_TEST_FOR_EXCEPTION (nImagePts < 2, Teuchos::Exceptions::InvalidParameter, std::endl
00225 << "Saddle Point needs more than 2 image pts (" << nImagePts << " given)" << std::endl);
00226
00227
00228 if( outputFilename.length() > 0) {
00229 std::fstream out;
00230 if(appendOutput) {
00231 out.open(outputFilename.c_str(), std::fstream::out | std::fstream::app);
00232 out << std::endl << "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%" << std::endl;
00233 }
00234 else out.open(outputFilename.c_str(), std::fstream::out);
00235 out.close();
00236 }
00237
00238
00239
00240
00241 initializeImagePoints(current_time, xdot, x, p, g, dbMode);
00242
00243 if(maxIterations > 0) {
00244
00245 doNudgedElasticBand(current_time, xdot, x, p, g, dbMode);
00246 }
00247 else {
00248
00249 int nFirstLeg = (nImagePts+1)/2, iCenter = nFirstLeg-1;
00250 iSaddlePt = iCenter;
00251 }
00252
00253
00254 doLevelSet(current_time, xdot, x, p, g, dbMode);
00255
00256
00257 if(maxIterations > 0 && maxFinalPts > 0) {
00258 initializeFinalImagePoints(current_time, xdot, x, p, g, dbMode);
00259 getFinalImagePointValues(current_time, xdot, x, p, g, dbMode);
00260
00261
00262 if( outputFilename.length() > 0) {
00263 std::fstream out; double pathLength = 0.0;
00264 out.open(outputFilename.c_str(), std::fstream::out | std::fstream::app);
00265 out << std::endl << std::endl << "% Saddle point path - interpolated 'final' points" << std::endl;
00266 out << "% index xCoord yCoord value pathLength pointRadius" << std::endl;
00267 for(std::size_t i=0; i<finalPts.size(); i++) {
00268 out << i << " " << finalPts[i].coords[0] << " " << finalPts[i].coords[1]
00269 << " " << finalPts[i].value << " " << pathLength << " " << finalPts[i].radius << std::endl;
00270 if(i < (finalPts.size()-1)) pathLength += finalPts[i].coords.distanceTo(finalPts[i+1].coords);
00271 }
00272 out.close();
00273 }
00274 }
00275
00276
00277 fillSaddlePointData(current_time, xdot, x, p, g, dbMode);
00278
00279 return;
00280 }
00281
00282
00283 void
00284 QCAD::SaddleValueResponseFunction::
00285 initializeImagePoints(const double current_time,
00286 const Epetra_Vector* xdot,
00287 const Epetra_Vector& x,
00288 const Teuchos::Array<ParamVec>& p,
00289 Epetra_Vector& g, int dbMode)
00290 {
00291
00292
00293
00294
00295
00296 if(dbMode > 1) std::cout << "Saddle Point: Beginning end point location" << std::endl;
00297
00298
00299 imagePts[0].init(numDims, imagePtSize);
00300 imagePts[nImagePts-1].init(numDims, imagePtSize);
00301
00302 mode = "Point location";
00303 Albany::FieldManagerScalarResponseFunction::evaluateResponse(
00304 current_time, xdot, NULL, x, p, g);
00305 if(dbMode > 2) std::cout << "Saddle Point: -- done evaluation" << std::endl;
00306
00307 if(beginRegionType == "Point") {
00308 imagePts[0].coords = beginPolygon[0];
00309 }
00310 else {
00311
00312
00313 double globalMin; int procToBcast, winner;
00314 comm->MinAll( &imagePts[0].value, &globalMin, 1);
00315 if( fabs(imagePts[0].value - globalMin) < 1e-8 )
00316 procToBcast = comm->MyPID();
00317 else procToBcast = -1;
00318
00319 comm->MaxAll( &procToBcast, &winner, 1 );
00320 comm->Broadcast( imagePts[0].coords.data(), numDims, winner);
00321 imagePts[0].value = globalMin;
00322 }
00323
00324 if(endRegionType == "Point") {
00325 imagePts[nImagePts-1].coords = endPolygon[0];
00326 }
00327 else {
00328
00329
00330 double globalMin; int procToBcast, winner;
00331 comm->MinAll( &imagePts[nImagePts-1].value, &globalMin, 1);
00332 if( fabs(imagePts[nImagePts-1].value - globalMin) < 1e-8 )
00333 procToBcast = comm->MyPID();
00334 else procToBcast = -1;
00335
00336 comm->MaxAll( &procToBcast, &winner, 1 );
00337 comm->Broadcast( imagePts[nImagePts-1].coords.data(), numDims, winner);
00338 imagePts[nImagePts-1].value = globalMin;
00339 }
00340
00342 if(shortenBeginPc > 1e-6) {
00343 if(saddleGuessGiven)
00344 imagePts[0].coords = imagePts[0].coords + (saddlePointGuess - imagePts[0].coords) * (shortenBeginPc/100.0);
00345 else
00346 imagePts[0].coords = imagePts[0].coords + (imagePts[nImagePts-1].coords - imagePts[0].coords) * (shortenBeginPc/100.0);
00347 }
00348 if(shortenEndPc > 1e-6) {
00349 if(saddleGuessGiven)
00350 imagePts[nImagePts-1].coords = imagePts[nImagePts-1].coords + (saddlePointGuess - imagePts[nImagePts-1].coords) * (shortenEndPc/100.0);
00351 else
00352 imagePts[nImagePts-1].coords = imagePts[nImagePts-1].coords + (imagePts[0].coords - imagePts[nImagePts-1].coords) * (shortenEndPc/100.0);
00353 }
00354
00355 if(dbMode > 2) std::cout << "Saddle Point: -- done begin/end point initialization" << std::endl;
00356
00358
00359
00360 const mathVector& initialPt = imagePts[0].coords;
00361 const mathVector& finalPt = imagePts[nImagePts-1].coords;
00362
00363
00364 if(bLockToPlane && numDims > 2)
00365 imagePts[0].coords[2] = imagePts[nImagePts-1].coords[2] = lockedZ;
00366
00367 if(saddleGuessGiven) {
00368
00369
00370 int nFirstLeg = (nImagePts+1)/2, nSecondLeg = nImagePts - nFirstLeg + 1;
00371 for(int i=1; i<nFirstLeg-1; i++) {
00372 double s = i * 1.0/(nFirstLeg-1);
00373 imagePts[i].init(initialPt + (saddlePointGuess - initialPt) * s, imagePtSize);
00374 }
00375 for(int i=0; i<nSecondLeg-1; i++) {
00376 double s = i * 1.0/(nSecondLeg-1);
00377 imagePts[i+nFirstLeg-1].init(saddlePointGuess + (finalPt - saddlePointGuess) * s, imagePtSize);
00378 }
00379 }
00380 else {
00381
00382
00383 for(std::size_t i=1; i<nImagePts-1; i++) {
00384 double s = i * 1.0/(nImagePts-1);
00385 imagePts[i].init(initialPt + (finalPt - initialPt) * s, imagePtSize);
00386 }
00387 }
00388
00389
00390 if(dbMode > 1) {
00391 for(std::size_t i=0; i<nImagePts; i++)
00392 std::cout << "Saddle Point: -- imagePt[" << i << "] = " << imagePts[i].coords << std::endl;
00393 }
00394
00395
00396
00397 if(bAggregateWorksets) {
00398 vFieldValues.clear();
00399 vCoords.clear();
00400 vGrads.clear();
00401
00402 mode = "Accumulate all field data";
00403 Albany::FieldManagerScalarResponseFunction::evaluateResponse(
00404 current_time, xdot, NULL, x, p, g);
00405
00406 }
00407
00408
00409 return;
00410 }
00411
00412 void
00413 QCAD::SaddleValueResponseFunction::
00414 initializeFinalImagePoints(const double current_time,
00415 const Epetra_Vector* xdot,
00416 const Epetra_Vector& x,
00417 const Teuchos::Array<ParamVec>& p,
00418 Epetra_Vector& g, int dbMode)
00419 {
00420
00421
00422
00423 if(dbMode > 1) std::cout << "Saddle Point: Initializing Final Image Points" << std::endl;
00424
00425 int maxPoints = maxFinalPts;
00426
00427 double* segmentLength = new double[nImagePts-1];
00428 double lengthBefore = 0.0, lengthAfter = 0.0;
00429 double radius = 0.0;
00430 int nPtsBefore = 0, nPtsAfter = 0, nFinalPts;
00431
00432
00433 for(std::size_t i = 0; i < nImagePts-1; i++) {
00434 segmentLength[i] = imagePts[i].coords.distanceTo(imagePts[i+1].coords);
00435 radius += imagePts[i].radius;
00436 if( (int)i < iSaddlePt ) lengthBefore += segmentLength[i];
00437 else lengthAfter += segmentLength[i];
00438 }
00439
00440 radius += imagePts[nImagePts-1].radius;
00441 radius /= nImagePts;
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462 double ptSpacing = (lengthBefore + lengthAfter)/(maxPoints-1);
00463
00464
00465
00466
00467
00468 nFinalPts = maxPoints;
00469
00470 finalPts.resize(nFinalPts);
00471 finalPtValues.resize(nFinalPts);
00472 finalPtWeights.resize(nFinalPts);
00473
00479
00480
00481 finalPts[0].init(imagePts[0].coords, imagePts[0].radius);
00482 finalPts[nFinalPts-1].init(imagePts[nImagePts-1].coords, imagePts[nImagePts-1].radius);
00483
00484 double offset = ptSpacing;
00485 int iCurFinalPt = 1;
00486
00487 for(std::size_t i = 0; i < nImagePts-1; i++) {
00488 const mathVector& initialPt = imagePts[i].coords;
00489 const mathVector& v = (imagePts[i+1].coords - imagePts[i].coords) * (1.0/segmentLength[i]);
00490
00491 if(segmentLength[i] > offset) {
00492 int nPtSegs = int((segmentLength[i]-offset) / ptSpacing);
00493 int nPts = nPtSegs + 1;
00494 double leftover = (segmentLength[i]-offset) - ptSpacing * nPtSegs;
00495
00496 for(int j = 0; j < nPts && iCurFinalPt < nFinalPts; j++) {
00497 finalPts[iCurFinalPt].init(initialPt + v * (ptSpacing * j + offset), radius );
00498 iCurFinalPt++;
00499 }
00500 offset = ptSpacing - leftover;
00501 }
00502 else {
00503 offset -= segmentLength[i];
00504 }
00505 }
00506
00507
00508 for(int j = iCurFinalPt; j < nFinalPts; j++)
00509 finalPts[j].init(imagePts[nImagePts-1].coords, imagePts[nImagePts-1].radius);
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570 return;
00571 }
00572
00573
00574 void
00575 QCAD::SaddleValueResponseFunction::
00576 doNudgedElasticBand(const double current_time,
00577 const Epetra_Vector* xdot,
00578 const Epetra_Vector& x,
00579 const Teuchos::Array<ParamVec>& p,
00580 Epetra_Vector& g, int dbMode)
00581 {
00582
00583
00584
00585
00586 std::size_t nIters, nInitialIterations;
00587 double dp, s;
00588 double gradScale, springScale, springBase;
00589 double avgForce=0, avgOpposingForce=0;
00590 double dt = maxTimeStep;
00591 double dt2 = dt*dt;
00592 double acceptedHighestPtGradNorm = -1.0, highestPtGradNorm;
00593 int iHighestPt, nConsecLowForceDiff=0;
00594
00595 mathVector tangent(numDims);
00596 std::vector<mathVector> force(nImagePts), lastForce(nImagePts), lastPositions(nImagePts), lastVelocities(nImagePts);
00597 std::vector<double> springConstants(nImagePts-1, minSpringConstant);
00598
00599
00600 for(std::size_t i=0; i<nImagePts; i++) {
00601 force[i].resize(numDims); force[i].fill(0.0);
00602 lastForce[i] = force[i];
00603 lastPositions[i] = imagePts[i].coords;
00604 lastVelocities[i] = imagePts[i].velocity;
00605 }
00606
00607
00608 double max_dCoords = imagePts[0].coords.distanceTo( imagePts[nImagePts-1].coords ) / nImagePts;
00609
00610 nIters = 0;
00611 nInitialIterations = 20;
00612
00613
00614 double* globalPtValues = new double [nImagePts];
00615 double* globalPtWeights = new double [nImagePts];
00616 double* globalPtGrads = new double [nImagePts*numDims];
00617
00618
00619 std::fstream fDebug;
00620 if(debugFilename.length() > 0) {
00621 fDebug.open(debugFilename.c_str(), std::fstream::out);
00622 fDebug << "% HighestValue HighestIndex AverageForce TimeStep"
00623 << " HighestPtGradNorm AverageOpposingForce SpringBase" << std::endl;
00624 }
00625
00626
00627 while( ++nIters <= maxIterations) {
00628
00629 if(dbMode > 1) std::cout << "Saddle Point: NEB Algorithm iteration " << nIters << " -----------------------" << std::endl;
00630 writeOutput(nIters);
00631
00632
00633 if(nIters > 1) {
00634
00635
00636 for(std::size_t i=1; i<nImagePts-1; i++) {
00637 dp = imagePts[i].velocity.dot(force[i]);
00638 if(dp < 0) imagePts[i].velocity.fill(0.0);
00639
00640
00641
00642 lastPositions[i] = imagePts[i].coords;
00643 lastVelocities[i] = imagePts[i].velocity;
00644
00645
00646 mathVector dCoords = lastVelocities[i] * dt + force[i] * dt2 * 0.5;
00647 imagePts[i].coords = lastPositions[i] + dCoords;
00648 imagePts[i].velocity = lastVelocities[i] + force[i] * dt;
00649 }
00650 }
00651
00652 getImagePointValues(current_time, xdot, x, p, g,
00653 globalPtValues, globalPtWeights, globalPtGrads,
00654 lastPositions, dbMode);
00655 iHighestPt = getHighestPtIndex();
00656 highestPtGradNorm = imagePts[iHighestPt].grad.norm();
00657
00658
00659 if(nIters == 1) initialIterationSetup(gradScale, springScale, dbMode);
00660
00661
00662 if(nIters > backtraceAfterIters) {
00663 while(dt > minTimeStep && highestPtGradNorm > acceptedHighestPtGradNorm) {
00664
00665
00666 dt = (dt/2 < minTimeStep) ? minTimeStep : dt/2;
00667 dt /= 2; dt2=dt*dt;
00668
00669 if(dbMode > 2) std::cout << "Saddle Point: ** Backtrace dt => " << dt << std::endl;
00670
00671
00672
00673 for(std::size_t i=1; i<nImagePts-1; i++) {
00674 mathVector dCoords = lastVelocities[i] * dt + force[i] * dt2 * 0.5;
00675 imagePts[i].coords = lastPositions[i] + dCoords;
00676 imagePts[i].velocity = lastVelocities[i] + force[i] * dt;
00677 }
00678
00679 getImagePointValues(current_time, xdot, x, p, g,
00680 globalPtValues, globalPtWeights, globalPtGrads,
00681 lastPositions, dbMode);
00682 iHighestPt = getHighestPtIndex();
00683 highestPtGradNorm = imagePts[iHighestPt].grad.norm();
00684 }
00685
00686 if(dt == minTimeStep && highestPtGradNorm > acceptedHighestPtGradNorm && dbMode > 2)
00687 std::cout << "Saddle Point: ** Warning: backtrace hit min dt == " << dt << std::endl;
00688 }
00689 acceptedHighestPtGradNorm = highestPtGradNorm;
00690
00691
00692 s = ((double)nIters-1.0)/maxIterations;
00693 springBase = springScale * ( (1.0-s)*minSpringConstant + s*maxSpringConstant );
00694 for(std::size_t i=0; i<nImagePts-1; i++) springConstants[i] = springBase;
00695
00696 avgForce = avgOpposingForce = 0.0;
00697
00698
00699 for(std::size_t i=1; i<nImagePts-1; i++) {
00700 if(dbMode > 2) std::cout << std::endl << "Saddle Point: >> Updating pt[" << i << "]:" << imagePts[i];
00701
00702
00703 computeTangent(i, tangent, dbMode);
00704
00705
00706 if((int)i == iHighestPt && bClimbing && nIters > nInitialIterations)
00707 computeClimbingForce(i, tangent, gradScale, force[i], dbMode);
00708 else
00709 computeForce(i, tangent, springConstants, gradScale, springScale,
00710 force[i], dt, dt2, dbMode);
00711
00712
00713 avgForce += force[i].norm();
00714 dp = force[i].dot(lastForce[i]) / (force[i].norm() * lastForce[i].norm());
00715 if( dp < 0 ) {
00716 mathVector v = force[i] - lastForce[i];
00717 avgOpposingForce += v.norm() / (force[i].norm() + lastForce[i].norm());
00718
00719 }
00720 }
00721
00722 avgForce /= (nImagePts-2);
00723 avgOpposingForce /= (nImagePts-2);
00724
00725
00726
00727 if(dbMode > 1)
00728 std::cout << "Saddle Point: ** Summary:"
00729 << " highest val[" << iHighestPt << "] = " << imagePts[iHighestPt].value
00730 << " AverageForce = " << avgForce << " dt = " << dt
00731 << " gradNorm = " << imagePts[iHighestPt].grad.norm()
00732 << " AvgOpposingForce = " << avgOpposingForce
00733 << " SpringBase = " << springBase << std::endl;
00734 if(debugFilename.length() > 0)
00735 fDebug << imagePts[iHighestPt].value << " " << iHighestPt << " "
00736 << avgForce << " " << dt << " " << imagePts[iHighestPt].grad.norm() << " "
00737 << avgOpposingForce << " " << springBase << std::endl;
00738
00739
00740
00741 if(imagePts[iHighestPt].grad.norm() < convergeTolerance) {
00742 if(dbMode > 2) std::cout << "Saddle Point: ** Converged (grad norm " <<
00743 imagePts[iHighestPt].grad.norm() << " < " << convergeTolerance << ")" << std::endl;
00744 break;
00745 }
00746 else if(nIters == maxIterations) break;
00747
00748
00749
00750 for(std::size_t i=1; i<nImagePts-1; i++) lastForce[i] = force[i];
00751
00752
00753
00754 if(avgOpposingForce < 1e-6) nConsecLowForceDiff++; else nConsecLowForceDiff = 0;
00755 if(nConsecLowForceDiff >= 3 && dt < maxTimeStep) {
00756 dt *= 2; dt2=dt*dt; nConsecLowForceDiff = 0;
00757 if(dbMode > 2) std::cout << "Saddle Point: ** Consecutive low dForce => dt = " << dt << std::endl;
00758 }
00759
00760
00761
00762 if(bLockToPlane && numDims > 2) {
00763 for(std::size_t i=1; i<nImagePts-1; i++) force[i][2] = 0.0;
00764 }
00765
00766
00767 bool reduce_dt = true;
00768 while(reduce_dt && dt/2 > minTimeStep) {
00769 reduce_dt = false;
00770 for(std::size_t i=1; i<nImagePts-1; i++) {
00771 if(imagePts[i].velocity.norm() * dt > max_dCoords) { reduce_dt = true; break; }
00772 if(0.5 * force[i].norm() * dt2 > max_dCoords) { reduce_dt = true; break; }
00773 }
00774 if(reduce_dt) {
00775 dt /= 2; dt2=dt*dt;
00776 if(dbMode > 2) std::cout << "Saddle Point: ** Warning: dCoords too large: dt => " << dt << std::endl;
00777 }
00778 }
00779
00780
00781
00782 if(bAdaptivePointSize) {
00783 for(std::size_t i=0; i<nImagePts; i++) {
00784 if(imagePts[i].weight < minAdaptivePointWt) imagePts[i].radius *= 2;
00785 else if(imagePts[i].weight > maxAdaptivePointWt) imagePts[i].radius /= 2;
00786 }
00787 }
00788
00789 }
00790
00791
00792 delete [] globalPtValues;
00793 delete [] globalPtWeights;
00794 delete [] globalPtGrads;
00795
00796
00797 if(dbMode) {
00798 if(nIters <= maxIterations)
00799 std::cout << "Saddle Point: NEB Converged after " << nIters << " iterations" << std::endl;
00800 else
00801 std::cout << "Saddle Point: NEB Giving up after " << maxIterations << " iterations" << std::endl;
00802
00803 for(std::size_t i=0; i<nImagePts; i++) {
00804 std::cout << "Saddle Point: -- Final pt[" << i << "] = " << imagePts[i].value
00805 << " : " << imagePts[i].coords << " (wt = " << imagePts[i].weight << " )"
00806 << " (r= " << imagePts[i].radius << " )" << std::endl;
00807 }
00808 }
00809
00810
00811 std::size_t imax = 0;
00812 for(std::size_t i=0; i<nImagePts; i++) {
00813 if(imagePts[i].weight > 0) { imax = i; break; }
00814 }
00815 for(std::size_t i=imax+1; i<nImagePts; i++) {
00816 if(imagePts[i].value > imagePts[imax].value && imagePts[i].weight > 0) imax = i;
00817 }
00818 iSaddlePt = imax;
00819
00820 if(debugFilename.length() > 0) fDebug.close();
00821 return;
00822 }
00823
00824 void
00825 QCAD::SaddleValueResponseFunction::
00826 fillSaddlePointData(const double current_time,
00827 const Epetra_Vector* xdot,
00828 const Epetra_Vector& x,
00829 const Teuchos::Array<ParamVec>& p,
00830 Epetra_Vector& g, int dbMode)
00831 {
00832 if(dbMode > 1) std::cout << "Saddle Point: Begin filling saddle point data" << std::endl;
00833
00834 if(bAggregateWorksets) {
00835 xmin = -1e10; xmax = 1e10; ymin = -1e10; ymax = 1e10;
00836 }
00837
00838 mode = "Fill saddle point";
00839 Albany::FieldManagerScalarResponseFunction::evaluateResponse(
00840 current_time, xdot, NULL, x, p, g);
00841 if(dbMode > 1) std::cout << "Saddle Point: Done filling saddle point data" << std::endl;
00842
00843
00844
00845
00846 returnFieldVal = g[0];
00847 imagePts[iSaddlePt].value = g[1];
00848
00849
00850 for(std::size_t i=0; i<numDims; i++) g[2+i] = imagePts[iSaddlePt].coords[i];
00851
00852 if(dbMode) {
00853 std::cout << "Saddle Point: Return Field value = " << g[0] << std::endl;
00854 std::cout << "Saddle Point: Field value = " << g[1] << std::endl;
00855 for(std::size_t i=0; i<numDims; i++)
00856 std::cout << "Saddle Point: Coord[" << i << "] = " << g[2+i] << std::endl;
00857 }
00858
00859 if( outputFilename.length() > 0) {
00860 std::fstream out; double pathLength = 0.0;
00861 out.open(outputFilename.c_str(), std::fstream::out | std::fstream::app);
00862 out << std::endl << std::endl << "% Saddle point path - Image points" << std::endl;
00863 out << "% index xCoord yCoord value pathLength pointRadius" << std::endl;
00864 for(std::size_t i=0; i<nImagePts; i++) {
00865 out << i << " " << imagePts[i].coords[0] << " " << imagePts[i].coords[1]
00866 << " " << imagePts[i].value << " " << pathLength << " " << imagePts[i].radius << std::endl;
00867 if(i<nImagePts-1) pathLength += imagePts[i].coords.distanceTo(imagePts[i+1].coords);
00868 }
00869 out.close();
00870 }
00871
00872 return;
00873 }
00874
00875
00876
00877 void
00878 QCAD::SaddleValueResponseFunction::
00879 doLevelSet(const double current_time,
00880 const Epetra_Vector* xdot,
00881 const Epetra_Vector& x,
00882 const Teuchos::Array<ParamVec>& p,
00883 Epetra_Vector& g, int dbMode)
00884 {
00885 int result;
00886
00887 if( fabs(levelSetRadius) < 1e-9 ) return;
00888
00889 vlsFieldValues.clear(); vlsCellAreas.clear();
00890 for(std::size_t k=0; k<numDims; k++) vlsCoords[k].clear();
00891
00892 mode = "Level set data collection";
00893 Albany::FieldManagerScalarResponseFunction::evaluateResponse(
00894 current_time, xdot, NULL, x, p, g);
00895
00897 std::vector<double> allFieldVals;
00898 std::vector<double> allCellAreas;
00899 std::vector<double> allCoords[MAX_DIMENSIONS];
00900
00901 QCAD::gatherVector(vlsFieldValues, allFieldVals, *comm);
00902 QCAD::gatherVector(vlsCellAreas, allCellAreas, *comm);
00903 for(std::size_t k=0; k<numDims; k++)
00904 QCAD::gatherVector(vlsCoords[k], allCoords[k], *comm);
00905
00907 if( allFieldVals.size() == 0 ) return;
00908
00910 if(dbMode) {
00911 std::cout << std::endl << "--- Begin Saddle Level Set Algorithm ---" << std::endl;
00912 std::cout << "--- Saddle Level Set: local size (this proc) = " << vlsFieldValues.size()
00913 << ", gathered size (all procs) = " << allFieldVals.size() << std::endl;
00914 }
00915
00917 std::vector<int> ordering;
00918 QCAD::getOrdering(allFieldVals, ordering);
00919
00920
00922 double maxFieldVal = allFieldVals[0], minFieldVal = allFieldVals[0];
00923 double maxCoords[3], minCoords[3];
00924
00925 for(std::size_t k=0; k<numDims && k < 3; k++)
00926 maxCoords[k] = minCoords[k] = allCoords[k][0];
00927
00928 std::size_t N = allFieldVals.size();
00929 for(std::size_t i=0; i<N; i++) {
00930 for(std::size_t k=0; k<numDims && k < 3; k++) {
00931 if(allCoords[k][i] > maxCoords[k]) maxCoords[k] = allCoords[k][i];
00932 if(allCoords[k][i] < minCoords[k]) minCoords[k] = allCoords[k][i];
00933 }
00934 if(allFieldVals[i] > maxFieldVal) maxFieldVal = allFieldVals[i];
00935 if(allFieldVals[i] < minFieldVal) minFieldVal = allFieldVals[i];
00936 }
00937
00938 double avgCellLength = pow(QCAD::averageOfVector(allCellAreas), 0.5);
00939 double maxFieldDifference = fabs(maxFieldVal - minFieldVal);
00940 double currentSaddleValue = imagePts[iSaddlePt].value;
00941
00942
00943 if(dbMode > 1) {
00944 std::cout << "--- Saddle Level Set: max field difference = " << maxFieldDifference
00945 << ", avg cell length = " << avgCellLength << std::endl;
00946 }
00947
00949 double cutoffDistance, cutoffFieldVal, minDepth;
00950 cutoffDistance = avgCellLength * distanceCutoffFctr;
00951 cutoffFieldVal = maxFieldDifference * fieldCutoffFctr;
00952 minDepth = minPoolDepthFctr * (currentSaddleValue - minFieldVal) / 2.0;
00953
00954 result = FindSaddlePoint_LevelSet(allFieldVals, allCoords, ordering,
00955 cutoffDistance, cutoffFieldVal, minDepth, dbMode, g);
00956
00957 if(result == 0) {
00958
00959 for(std::size_t i=0; i<numDims; i++) imagePts[iSaddlePt].coords[i] = g[2+i];
00960 imagePts[iSaddlePt].value = g[1];
00961 imagePts[iSaddlePt].radius = 1e-5;
00962
00963 }
00964
00965 return;
00966 }
00967
00969 int QCAD::SaddleValueResponseFunction::
00970 FindSaddlePoint_LevelSet(std::vector<double>& allFieldVals,
00971 std::vector<double>* allCoords, std::vector<int>& ordering,
00972 double cutoffDistance, double cutoffFieldVal, double minDepth, int dbMode,
00973 Epetra_Vector& g)
00974 {
00975 if(dbMode) {
00976 std::cout << "--- Saddle Level Set: distance cutoff = " << cutoffDistance
00977 << ", field cutoff = " << cutoffFieldVal
00978 << ", min depth = " << minDepth << std::endl;
00979 }
00980
00981
00982
00983
00984 std::size_t N = allFieldVals.size();
00985 std::vector<int> treeIDs(N, -1);
00986 std::vector<double> minFieldVals;
00987 std::vector<int> treeSizes;
00988 int nextAvailableTreeID = 0;
00989
00990 int nTrees = 0, nMaxTrees = 0;
00991 int nDeepTrees=0, lastDeepTrees=0, treeIDtoReplace;
00992 int I, J, K;
00993 for(std::size_t i=0; i < N; i++) {
00994 I = ordering[i];
00995
00996 if(dbMode > 1) {
00997 nDeepTrees = 0;
00998 for(std::size_t t=0; t < treeSizes.size(); t++) {
00999 if(treeSizes[t] > 0 && (allFieldVals[I]-minFieldVals[t]) > minDepth) nDeepTrees++;
01000 }
01001 }
01002
01003 if(dbMode > 3) std::cout << "DEBUG: i=" << i << "( I = " << I << "), val="
01004 << allFieldVals[I] << ", loc=(" << allCoords[0][I]
01005 << "," << allCoords[1][I] << ")" << " nD=" << nDeepTrees;
01006
01007 if(dbMode > 1 && lastDeepTrees != nDeepTrees) {
01008 std::cout << "--- Saddle: i=" << i << " new deep pool: nPools=" << nTrees
01009 << " nDeep=" << nDeepTrees << std::endl;
01010 lastDeepTrees = nDeepTrees;
01011 }
01012
01013 for(int j=i-1; j >= 0 && fabs(allFieldVals[I] - allFieldVals[ordering[j]]) < cutoffFieldVal; j--) {
01014 J = ordering[j];
01015
01016 if( QCAD::distance(allCoords, I, J, numDims) < cutoffDistance ) {
01017 if(treeIDs[I] == -1) {
01018 treeIDs[I] = treeIDs[J];
01019 treeSizes[treeIDs[I]]++;
01020
01021 if(dbMode > 3) std::cout << " --> tree " << treeIDs[J]
01022 << " ( size=" << treeSizes[treeIDs[J]] << ", depth="
01023 << (allFieldVals[I]-minFieldVals[treeIDs[J]]) << ")" << std::endl;
01024 }
01025 else if(treeIDs[I] != treeIDs[J]) {
01026
01027
01028 nDeepTrees = 0;
01029 for(std::size_t t=0; t < treeSizes.size(); t++) {
01030 if(treeSizes[t] > 0 && (allFieldVals[I]-minFieldVals[t]) > minDepth) nDeepTrees++;
01031 }
01032
01033 bool mergingTwoDeepTrees = false;
01034 if((allFieldVals[I]-minFieldVals[treeIDs[I]]) > minDepth &&
01035 (allFieldVals[I]-minFieldVals[treeIDs[J]]) > minDepth) {
01036 mergingTwoDeepTrees = true;
01037 nDeepTrees--;
01038 }
01039
01040 treeIDtoReplace = treeIDs[I];
01041 if( minFieldVals[treeIDtoReplace] < minFieldVals[treeIDs[J]] )
01042 minFieldVals[treeIDs[J]] = minFieldVals[treeIDtoReplace];
01043
01044 for(int k=i; k >=0; k--) {
01045 K = ordering[k];
01046 if(treeIDs[K] == treeIDtoReplace) {
01047 treeIDs[K] = treeIDs[J];
01048 treeSizes[treeIDs[J]]++;
01049 }
01050 }
01051 treeSizes[treeIDtoReplace] = 0;
01052 nTrees -= 1;
01053
01054 if(dbMode > 3) std::cout << "DEBUG: also --> " << treeIDs[J]
01055 << " [merged] size=" << treeSizes[treeIDs[J]]
01056 << " (treecount after merge = " << nTrees << ")" << std::endl;
01057
01058 if(dbMode > 1) std::cout << "--- Saddle: i=" << i << "merge: nPools=" << nTrees
01059 << " nDeep=" << nDeepTrees << std::endl;
01060
01061
01062 if(mergingTwoDeepTrees && nDeepTrees == 1) {
01063 if(dbMode > 3) std::cout << "DEBUG: FOUND SADDLE! exiting." << std::endl;
01064 if(dbMode > 1) std::cout << "--- Saddle: i=" << i << " Found saddle at ";
01065
01066
01067 g[0] = 0;
01068 g[1] = allFieldVals[I];
01069 for(std::size_t k=0; k<numDims && k < 3; k++) {
01070 g[2+k] = allCoords[k][I];
01071 if(dbMode > 1) std::cout << allCoords[k][I] << ", ";
01072 }
01073
01074 if(dbMode > 1) std::cout << "ret=" << g[0] << std::endl;
01075 return 0;
01076 }
01077
01078 }
01079 }
01080
01081 }
01082
01083 if(treeIDs[I] == -1) {
01084 if(dbMode > 3) std::cout << " --> new tree with ID " << nextAvailableTreeID
01085 << " (treecount after new = " << (nTrees+1) << ")" << std::endl;
01086 if(dbMode > 1) std::cout << "--- Saddle: i=" << i << " new pool: nPools=" << (nTrees+1)
01087 << " nDeep=" << nDeepTrees << std::endl;
01088
01089 treeIDs[I] = nextAvailableTreeID++;
01090 minFieldVals.push_back(allFieldVals[I]);
01091 treeSizes.push_back(1);
01092
01093 nTrees += 1;
01094 if(nTrees > nMaxTrees) nMaxTrees = nTrees;
01095 }
01096
01097 }
01098
01099
01100 if(dbMode > 3) std::cout << "DEBUG: NO SADDLE. exiting." << std::endl;
01101 for(std::size_t k=0; k<5; k++) g[k] = 0;
01102
01103
01104
01105 if(nMaxTrees >= 2) return 1;
01106
01107
01108 return 2;
01109 }
01110
01111
01112 double QCAD::SaddleValueResponseFunction::getCurrent
01113 (const double& lattTemp, const Teuchos::RCP<QCAD::MaterialDatabase>& materialDB) const
01114 {
01115 const double kB = 8.617332e-5;
01116 double Temp = lattTemp;
01117
01118
01119 double* segmentLength = new double[nImagePts-1];
01120
01121
01122 double lengthBefore = 0.0, lengthAfter = 0.0;
01123
01124
01125 for(std::size_t i = 0; i < nImagePts-1; i++)
01126 {
01127 segmentLength[i] = imagePts[i].coords.distanceTo(imagePts[i+1].coords);
01128 if( (int)i < iSaddlePt )
01129 lengthBefore += segmentLength[i];
01130 else
01131 lengthAfter += segmentLength[i];
01132 }
01133
01134
01135
01136
01137
01138
01139
01140 double ptSpacing = gfGridSpacing;
01141 int nGFPts = int( (lengthBefore + lengthAfter)/gfGridSpacing );
01142 std::cout << "nGFPts = " << nGFPts << ", actual gfGridSpacing = " << ptSpacing << std::endl;
01143
01144
01145 std::string refMtrlName = materialDB->getParam<std::string>("Reference Material");
01146 double effMass = materialDB->getMaterialParam<double>(refMtrlName,"Transverse Electron Effective Mass");
01147
01148
01149 double matChi = materialDB->getMaterialParam<double>(refMtrlName,"Electron Affinity");
01150
01151
01152 Teuchos::RCP<std::vector<double> > pot = Teuchos::rcp( new std::vector<double>(finalPts.size()) );
01153 for(std::size_t i = 0; i < finalPts.size(); i++)
01154 (*pot)[i] = finalPts[i].value / fieldScaling;
01155
01156
01157 double qPhiRef;
01158 {
01159 std::string category = materialDB->getMaterialParam<std::string>(refMtrlName,"Category");
01160 if (category == "Semiconductor")
01161 {
01162
01163 double mdn = materialDB->getMaterialParam<double>(refMtrlName,"Electron DOS Effective Mass");
01164 double mdp = materialDB->getMaterialParam<double>(refMtrlName,"Hole DOS Effective Mass");
01165 double Chi = materialDB->getMaterialParam<double>(refMtrlName,"Electron Affinity");
01166 double Eg0 = materialDB->getMaterialParam<double>(refMtrlName,"Zero Temperature Band Gap");
01167 double alpha = materialDB->getMaterialParam<double>(refMtrlName,"Band Gap Alpha Coefficient");
01168 double beta = materialDB->getMaterialParam<double>(refMtrlName,"Band Gap Beta Coefficient");
01169
01170 double Eg = Eg0 - alpha*pow(Temp,2.0)/(beta+Temp);
01171 double kbT = kB * Temp;
01172 double Eic = -Eg/2. + 3./4.*kbT*log(mdp/mdn);
01173 qPhiRef = Chi - Eic;
01174 }
01175 else
01176 TEUCHOS_TEST_FOR_EXCEPTION (true, Teuchos::Exceptions::InvalidParameter, std::endl
01177 << "Error! Invalid category " << category << " for reference material !" << std::endl);
01178 }
01179
01180
01181 Teuchos::RCP<std::vector<double> > Ec = Teuchos::rcp( new std::vector<double>(finalPts.size()) );
01182 Teuchos::RCP<std::vector<double> > pathLen = Teuchos::rcp( new std::vector<double>(finalPts.size()) );
01183
01184 double pathLength = 0.0;
01185 for(std::size_t i = 0; i < finalPts.size(); i++)
01186 {
01187 (*Ec)[i] = qPhiRef - matChi - (*pot)[i];
01188 (*pathLen)[i] = pathLength;
01189 if (i < (finalPts.size()-1))
01190 pathLength += finalPts[i].coords.distanceTo(finalPts[i+1].coords);
01191 }
01192
01193
01194 if( outputFilename.length() > 0)
01195 {
01196 std::fstream out;
01197 out.open(outputFilename.c_str(), std::fstream::out | std::fstream::app);
01198 out << std::endl << std::endl << "% Computed conduction band Ec (assumes field is Potential) -- 'final' points" << std::endl;
01199 out << "% index xCoord yCoord Ec pathLength pointRadius" << std::endl;
01200 for(std::size_t i = 0; i < finalPts.size(); i++)
01201 {
01202 out << i << " " << finalPts[i].coords[0] << " " << finalPts[i].coords[1]
01203 << " " << (*Ec)[i] << " " << (*pathLen)[i] << " " << finalPts[i].radius << std::endl;
01204 }
01205 out.close();
01206 }
01207
01208 double I = 0.0;
01209
01210
01211 QCAD::GreensFunctionTunnelingSolver solver(Ec, pathLen, nGFPts, ptSpacing, effMass, comm, outputFilename);
01212
01213
01214 bool bUseAnasazi = false;
01215 if (gfEigensolver == "Anasazi")
01216 bUseAnasazi = true;
01217 else if (gfEigensolver == "tql2")
01218 bUseAnasazi = false;
01219 else
01220 TEUCHOS_TEST_FOR_EXCEPTION (true, Teuchos::Exceptions::InvalidParameter, std::endl
01221 << "Error! Invalid GF-CBR Method Eigensolver, must be either Anasazi or tql2 !" << std::endl);
01222
01223
01224 if (bSweepVds)
01225 {
01226 int ptsVds = stepsVds + 1;
01227 std::vector<double> rangeVds(ptsVds, 0.0);
01228 std::vector<double> rangeIds(ptsVds, 0.0);
01229
01230 double deltaVds = (finalVds - initVds) / double(ptsVds-1);
01231 for (int i = 0; i < ptsVds; i++)
01232 rangeVds[i] = initVds + deltaVds * double(i);
01233
01234 solver.computeCurrentRange(rangeVds, kB * Temp, current_Ecutoff_offset_from_Emax, rangeIds, bUseAnasazi);
01235
01236
01237 I = rangeIds[ptsVds-1];
01238
01239
01240 if ( outputFilename.length() > 0)
01241 {
01242 std::fstream out;
01243 out.open(outputFilename.c_str(), std::fstream::out | std::fstream::app);
01244 out << std::endl << std::endl << "% Current vs Voltage IV curve (GF-CBR method)" << std::endl;
01245 out << "% index, Vds [V] vs Ids [A] data" << std::endl;
01246 for(std::size_t i = 0; i < rangeVds.size(); i++)
01247 out << i << " " << rangeVds[i] << " " << rangeIds[i] << " " << std::endl;
01248 out.close();
01249 }
01250
01251 }
01252
01253
01254 else
01255 I = solver.computeCurrent(finalVds, kB * Temp, current_Ecutoff_offset_from_Emax, bUseAnasazi);
01256
01257 std::cout << "Final Vds = " << finalVds << " V, Current Ids = " << I << " Amps" << std::endl;
01258
01259 return I;
01260 }
01261
01262
01263 void
01264 QCAD::SaddleValueResponseFunction::
01265 evaluateTangent(const double alpha,
01266 const double beta,
01267 const double omega,
01268 const double current_time,
01269 bool sum_derivs,
01270 const Epetra_Vector* xdot,
01271 const Epetra_Vector* xdotdot,
01272 const Epetra_Vector& x,
01273 const Teuchos::Array<ParamVec>& p,
01274 ParamVec* deriv_p,
01275 const Epetra_MultiVector* Vxdot,
01276 const Epetra_MultiVector* Vxdotdot,
01277 const Epetra_MultiVector* Vx,
01278 const Epetra_MultiVector* Vp,
01279 Epetra_Vector* g,
01280 Epetra_MultiVector* gx,
01281 Epetra_MultiVector* gp)
01282 {
01283
01284
01285 if(g != NULL) {
01286
01287
01288
01289
01290
01291
01292
01293
01294
01295
01296
01297
01298
01299
01300
01301 mode = "Fill saddle point";
01302 Albany::FieldManagerScalarResponseFunction::evaluateTangent(
01303 alpha, beta, omega, current_time, sum_derivs, xdot, xdotdot,
01304 x, p, deriv_p, Vxdot, Vxdotdot, Vx, Vp, g, gx, gp);
01305 }
01306 else {
01307 if (gx != NULL) gx->PutScalar(0.0);
01308 if (gp != NULL) gp->PutScalar(0.0);
01309 }
01310 }
01311
01312 void
01313 QCAD::SaddleValueResponseFunction::
01314 evaluateGradient(const double current_time,
01315 const Epetra_Vector* xdot,
01316 const Epetra_Vector* xdotdot,
01317 const Epetra_Vector& x,
01318 const Teuchos::Array<ParamVec>& p,
01319 ParamVec* deriv_p,
01320 Epetra_Vector* g,
01321 Epetra_MultiVector* dg_dx,
01322 Epetra_MultiVector* dg_dxdot,
01323 Epetra_MultiVector* dg_dxdotdot,
01324 Epetra_MultiVector* dg_dp)
01325 {
01326
01327
01328 if(g != NULL) {
01329
01330
01331 if(!matchesCurrentResults(*g))
01332 evaluateResponse(current_time, xdot, xdotdot, x, p, *g);
01333
01334 mode = "Fill saddle point";
01335 Albany::FieldManagerScalarResponseFunction::evaluateGradient(
01336 current_time, xdot, xdotdot, x, p, deriv_p, g, dg_dx, dg_dxdot, dg_dxdotdot, dg_dp);
01337 }
01338 else {
01339 if (dg_dx != NULL) dg_dx->PutScalar(0.0);
01340 if (dg_dxdot != NULL) dg_dxdot->PutScalar(0.0);
01341 if (dg_dp != NULL) dg_dp->PutScalar(0.0);
01342 }
01343 }
01344
01345 void
01346 QCAD::SaddleValueResponseFunction::
01347 postProcessResponses(const Epetra_Comm& comm_, const Teuchos::RCP<Epetra_Vector>& g)
01348 {
01349 }
01350
01351 void
01352 QCAD::SaddleValueResponseFunction::
01353 postProcessResponseDerivatives(const Epetra_Comm& comm_, const Teuchos::RCP<Epetra_MultiVector>& gt)
01354 {
01355 }
01356
01357
01358 void
01359 QCAD::SaddleValueResponseFunction::
01360 getImagePointValues(const double current_time,
01361 const Epetra_Vector* xdot,
01362 const Epetra_Vector& x,
01363 const Teuchos::Array<ParamVec>& p,
01364 Epetra_Vector& g,
01365 double* globalPtValues,
01366 double* globalPtWeights,
01367 double* globalPtGrads,
01368 std::vector<QCAD::mathVector> lastPositions,
01369 int dbMode)
01370 {
01371
01372 xmax = xmin = imagePts[0].coords[0];
01373 ymax = ymin = imagePts[0].coords[1];
01374 for(std::size_t i=1; i<nImagePts; i++) {
01375 xmin = std::min(imagePts[i].coords[0],xmin);
01376 xmax = std::max(imagePts[i].coords[0],xmax);
01377 ymin = std::min(imagePts[i].coords[1],ymin);
01378 ymax = std::max(imagePts[i].coords[1],ymax);
01379 }
01380 xmin -= 5*imagePtSize; xmax += 5*imagePtSize;
01381 ymin -= 5*imagePtSize; ymax += 5*imagePtSize;
01382
01383
01384 imagePtValues.fill(0.0);
01385 imagePtWeights.fill(0.0);
01386 imagePtGradComps.fill(0.0);
01387
01388 if(bAggregateWorksets) {
01389
01390 for(std::size_t i=0; i<vFieldValues.size(); i++) {
01391 addImagePointData( vCoords[i].data, vFieldValues[i], vGrads[i].data );
01392 }
01393 }
01394 else {
01395 mode = "Collect image point data";
01396 Albany::FieldManagerScalarResponseFunction::evaluateResponse(
01397 current_time, xdot, NULL, x, p, g);
01398 }
01399
01400
01401 comm->SumAll( imagePtValues.data(), globalPtValues, nImagePts );
01402 comm->SumAll( imagePtWeights.data(), globalPtWeights, nImagePts );
01403 comm->SumAll( imagePtGradComps.data(), globalPtGrads, nImagePts*numDims );
01404
01405
01406
01407 for(std::size_t i=0; i<nImagePts; i++) {
01408 imagePts[i].weight = globalPtWeights[i];
01409 if(globalPtWeights[i] > 1e-6) {
01410 imagePts[i].value = globalPtValues[i] / imagePts[i].weight;
01411 for(std::size_t k=0; k<numDims; k++)
01412 imagePts[i].grad[k] = globalPtGrads[k*nImagePts+i] / imagePts[i].weight;
01413 }
01414 else {
01415
01416 imagePts[i].grad.fill(0.0);
01417 imagePts[i].coords = lastPositions[i];
01418 }
01419 }
01420
01421 return;
01422 }
01423
01424 void
01425 QCAD::SaddleValueResponseFunction::
01426 getFinalImagePointValues(const double current_time,
01427 const Epetra_Vector* xdot,
01428 const Epetra_Vector& x,
01429 const Teuchos::Array<ParamVec>& p,
01430 Epetra_Vector& g,
01431 int dbMode)
01432 {
01433
01434 xmax = xmin = imagePts[0].coords[0];
01435 ymax = ymin = imagePts[0].coords[1];
01436 for(std::size_t i=1; i<nImagePts; i++) {
01437 xmin = std::min(imagePts[i].coords[0],xmin);
01438 xmax = std::max(imagePts[i].coords[0],xmax);
01439 ymin = std::min(imagePts[i].coords[1],ymin);
01440 ymax = std::max(imagePts[i].coords[1],ymax);
01441 }
01442 xmin -= 5*imagePtSize; xmax += 5*imagePtSize;
01443 ymin -= 5*imagePtSize; ymax += 5*imagePtSize;
01444
01445
01446 finalPtValues.fill(0.0);
01447 finalPtWeights.fill(0.0);
01448
01449 if(bAggregateWorksets) {
01450
01451 for(std::size_t i=0; i<vFieldValues.size(); i++) {
01452 addFinalImagePointData( vCoords[i].data, vFieldValues[i] );
01453 }
01454 }
01455 else {
01456 mode = "Collect final image point data";
01457 Albany::FieldManagerScalarResponseFunction::evaluateResponse(
01458 current_time, xdot, NULL, x, p, g);
01459 }
01460
01461
01462 std::size_t nFinalPts = finalPts.size();
01463 if(nFinalPts > 0) {
01464 double* globalPtValues = new double [nFinalPts];
01465 double* globalPtWeights = new double [nFinalPts];
01466 comm->SumAll( finalPtValues.data(), globalPtValues, nFinalPts );
01467 comm->SumAll( finalPtWeights.data(), globalPtWeights, nFinalPts );
01468
01469
01470 for(std::size_t i=0; i<nFinalPts; i++) {
01471 finalPts[i].weight = globalPtWeights[i];
01472 finalPts[i].grad.fill(0.0);
01473
01474 if(globalPtWeights[i] > 1e-6)
01475 finalPts[i].value = globalPtValues[i] / finalPts[i].weight;
01476 else
01477 finalPts[i].value = 0.0;
01478 }
01479 }
01480
01481 return;
01482 }
01483
01484
01485
01486 void
01487 QCAD::SaddleValueResponseFunction::
01488 writeOutput(int nIters)
01489 {
01490
01491 if( (nEvery > 0) && (nIters % nEvery == 1) && (outputFilename.length() > 0)) {
01492 std::fstream out; double pathLength = 0.0;
01493 out.open(outputFilename.c_str(), std::fstream::out | std::fstream::app);
01494 out << std::endl << std::endl << "% NEB Iteration " << nIters << std::endl;
01495 out << "% index xCoord yCoord value pathLength pointRadius" << std::endl;
01496 for(std::size_t i=0; i<nImagePts; i++) {
01497 out << i << " " << imagePts[i].coords[0] << " " << imagePts[i].coords[1]
01498 << " " << imagePts[i].value << " " << pathLength << " " << imagePts[i].radius << std::endl;
01499 if(i<nImagePts-1) pathLength += imagePts[i].coords.distanceTo(imagePts[i+1].coords);
01500 }
01501 out.close();
01502 }
01503 }
01504
01505 void
01506 QCAD::SaddleValueResponseFunction::
01507 initialIterationSetup(double& gradScale, double& springScale, int dbMode)
01508 {
01509 const QCAD::mathVector& initialPt = imagePts[0].coords;
01510 const QCAD::mathVector& finalPt = imagePts[nImagePts-1].coords;
01511
01512 double maxGradMag = 0.0, avgWeight = 0.0, ifDist;
01513 for(std::size_t i=0; i<nImagePts; i++) {
01514 maxGradMag = std::max(maxGradMag, imagePts[i].grad.norm());
01515 avgWeight += imagePts[i].weight;
01516 }
01517 ifDist = initialPt.distanceTo(finalPt);
01518 avgWeight /= nImagePts;
01519 gradScale = ifDist / maxGradMag;
01520
01521
01522
01523 springScale = (double) (nImagePts-1);
01524
01525 if(dbMode) std::cout << "Saddle Point: First iteration: maxGradMag=" << maxGradMag
01526 << " |init-final|=" << ifDist << " gradScale=" << gradScale
01527 << " springScale=" << springScale << " avgWeight=" << avgWeight << std::endl;
01528 return;
01529 }
01530
01531 void
01532 QCAD::SaddleValueResponseFunction::
01533 computeTangent(std::size_t i, QCAD::mathVector& tangent, int dbMode)
01534 {
01535
01536
01537 double dValuePrev = imagePts[i-1].value - imagePts[i].value;
01538 double dValueNext = imagePts[i+1].value - imagePts[i].value;
01539
01540 if(dValuePrev * dValueNext < 0.0) {
01541 double dmax = std::max( fabs(dValuePrev), fabs(dValueNext) );
01542 double dmin = std::min( fabs(dValuePrev), fabs(dValueNext) );
01543 if(imagePts[i-1].value > imagePts[i+1].value)
01544 tangent = (imagePts[i+1].coords - imagePts[i].coords) * dmin + (imagePts[i].coords - imagePts[i-1].coords) * dmax;
01545 else
01546 tangent = (imagePts[i+1].coords - imagePts[i].coords) * dmax + (imagePts[i].coords - imagePts[i-1].coords) * dmin;
01547 }
01548 else {
01549 if(imagePts[i+1].value > imagePts[i].value)
01550 tangent = (imagePts[i+1].coords - imagePts[i].coords);
01551 else
01552 tangent = (imagePts[i].coords - imagePts[i-1].coords);
01553 }
01554 tangent.normalize();
01555 return;
01556 }
01557
01558 void
01559 QCAD::SaddleValueResponseFunction::
01560 computeClimbingForce(std::size_t i, const QCAD::mathVector& tangent, const double& gradScale,
01561 QCAD::mathVector& force, int dbMode)
01562 {
01563
01564
01565 double dp = imagePts[i].grad.dot( tangent );
01566 force = (imagePts[i].grad * -1.0 + (tangent*dp) * 2) * gradScale;
01567
01568 if(dbMode > 2) {
01569 std::cout << "Saddle Point: -- tangent = " << tangent << std::endl;
01570 std::cout << "Saddle Point: -- grad along tangent = " << dp << std::endl;
01571 std::cout << "Saddle Point: -- total force (climbing) = " << force[i] << std::endl;
01572 }
01573 }
01574
01575 void
01576 QCAD::SaddleValueResponseFunction::
01577 computeForce(std::size_t i, const QCAD::mathVector& tangent, const std::vector<double>& springConstants,
01578 const double& gradScale, const double& springScale, QCAD::mathVector& force,
01579 double& dt, double& dt2, int dbMode)
01580 {
01581 force.fill(0.0);
01582
01583
01584 double dp = imagePts[i].grad.dot( tangent );
01585 force -= (imagePts[i].grad - tangent * dp) * gradScale;
01586
01587 if(dbMode > 2) {
01588 std::cout << "Saddle Point: -- tangent = " << tangent << std::endl;
01589 std::cout << "Saddle Point: -- grad along tangent = " << dp << std::endl;
01590 std::cout << "Saddle Point: -- grad force = " << force[i] << std::endl;
01591 }
01592
01593
01594 mathVector dNext(numDims), dPrev(numDims);
01595 mathVector parallelSpringForce(numDims), perpSpringForce(numDims);
01596 mathVector springForce(numDims);
01597
01598 dPrev = imagePts[i-1].coords - imagePts[i].coords;
01599 dNext = imagePts[i+1].coords - imagePts[i].coords;
01600
01601 double prevNorm = dPrev.norm();
01602 double nextNorm = dNext.norm();
01603
01604 double perpFactor = 0.5 * (1 + cos(3.141592 * fabs(dPrev.dot(dNext) / (prevNorm * nextNorm))));
01605 springForce = ((dNext * springConstants[i]) + (dPrev * springConstants[i-1]));
01606 parallelSpringForce = tangent * springForce.dot(tangent);
01607 perpSpringForce = (springForce - tangent * springForce.dot(tangent) );
01608
01609 springForce = parallelSpringForce + perpSpringForce * (perpFactor * antiKinkFactor);
01610 while(springForce.norm() * dt2 > std::max(dPrev.norm(),dNext.norm()) && dt > minTimeStep) {
01611 dt /= 2; dt2=dt*dt;
01612 if(dbMode > 2) std::cout << "Saddle Point: ** Warning: spring forces seem too large: dt => " << dt << std::endl;
01613 }
01614
01615 force += springForce;
01616
01617 if(dbMode > 2) {
01618 std::cout << "Saddle Point: -- spring force = " << springForce << std::endl;
01619 std::cout << "Saddle Point: -- total force = " << force[i] << std::endl;
01620 }
01621 }
01622
01623
01624
01625 std::string QCAD::SaddleValueResponseFunction::getMode()
01626 {
01627 return mode;
01628 }
01629
01630
01631 bool QCAD::SaddleValueResponseFunction::
01632 pointIsInImagePtRegion(const double* p, double refZ) const
01633 {
01634
01635 if(numDims > 2 && (refZ < zmin || refZ > zmax)) return false;
01636 return !(p[0] < xmin || p[1] < ymin || p[0] > xmax || p[1] > ymax);
01637 }
01638
01639 bool QCAD::SaddleValueResponseFunction::
01640 pointIsInAccumRegion(const double* p, double refZ) const
01641 {
01642
01643 if(numDims > 2 && (refZ < zmin || refZ > zmax)) return false;
01644 return true;
01645 }
01646
01647 bool QCAD::SaddleValueResponseFunction::
01648 pointIsInLevelSetRegion(const double* p, double refZ) const
01649 {
01650
01651 if(numDims > 2 && (refZ < zmin || refZ > zmax)) return false;
01652 return (imagePts[iSaddlePt].coords.distanceTo(p) < levelSetRadius);
01653 }
01654
01655
01656
01657 void QCAD::SaddleValueResponseFunction::
01658 addBeginPointData(const std::string& elementBlock, const double* p, double value)
01659 {
01660
01661 if( beginRegionType == "Point" ) return;
01662
01663
01664 if( beginRegionType == "Element Block" ) {
01665 if(elementBlock == beginElementBlock) {
01666 if( value < imagePts[0].value || imagePts[0].weight == 0 ) {
01667 imagePts[0].value = value;
01668 imagePts[0].weight = 1.0;
01669 imagePts[0].coords.fill(p);
01670 }
01671 }
01672 return;
01673 }
01674
01675
01676 if( beginRegionType == "Polygon" ) {
01677 if( QCAD::ptInPolygon(beginPolygon, p) ) {
01678 if( value < imagePts[0].value || imagePts[0].weight == 0 ) {
01679 imagePts[0].value = value;
01680 imagePts[0].weight = 1.0;
01681 imagePts[0].coords.fill(p);
01682 }
01683 }
01684 return;
01685 }
01686
01687 TEUCHOS_TEST_FOR_EXCEPTION (true, Teuchos::Exceptions::InvalidParameter, std::endl
01688 << "Invalid region type: " << beginRegionType << " for begin pt" << std::endl);
01689 return;
01690 }
01691
01692 void QCAD::SaddleValueResponseFunction::
01693 addEndPointData(const std::string& elementBlock, const double* p, double value)
01694 {
01695
01696 if( endRegionType == "Point" ) return;
01697
01698
01699 if( endRegionType == "Element Block" ) {
01700 if(elementBlock == endElementBlock) {
01701 if( value < imagePts[nImagePts-1].value || imagePts[nImagePts-1].weight == 0 ) {
01702 imagePts[nImagePts-1].value = value;
01703 imagePts[nImagePts-1].weight = 1.0;
01704 imagePts[nImagePts-1].coords.fill(p);
01705 }
01706 }
01707 return;
01708 }
01709
01710
01711 if( endRegionType == "Polygon" ) {
01712 if( QCAD::ptInPolygon(endPolygon, p) ) {
01713 if( value < imagePts[nImagePts-1].value || imagePts[nImagePts-1].weight == 0 ) {
01714 imagePts[nImagePts-1].value = value;
01715 imagePts[nImagePts-1].weight = 1.0;
01716 imagePts[nImagePts-1].coords.fill(p);
01717 }
01718 }
01719 return;
01720 }
01721
01722 TEUCHOS_TEST_FOR_EXCEPTION (true, Teuchos::Exceptions::InvalidParameter, std::endl
01723 << "Invalid region type: " << endRegionType << " for end pt" << std::endl);
01724 return;
01725 }
01726
01727
01728 void QCAD::SaddleValueResponseFunction::
01729 addImagePointData(const double* p, double value, double* grad)
01730 {
01731 double w, effDims = (bLockToPlane && numDims > 2) ? 2 : numDims;
01732 for(std::size_t i=0; i<nImagePts; i++) {
01733 w = pointFn(imagePts[i].coords.distanceTo(p) , imagePts[i].radius );
01734 if(w > 0) {
01735 imagePtWeights[i] += w;
01736 imagePtValues[i] += w*value;
01737 for(std::size_t k=0; k<effDims; k++)
01738 imagePtGradComps[k*nImagePts+i] += w*grad[k];
01739
01740
01741
01742 }
01743 }
01744 return;
01745 }
01746
01747 void QCAD::SaddleValueResponseFunction::
01748 addFinalImagePointData(const double* p, double value)
01749 {
01750 double w;
01751 for(std::size_t i=0; i< finalPts.size(); i++) {
01752 w = pointFn(finalPts[i].coords.distanceTo(p) , finalPts[i].radius );
01753 if(w > 0) {
01754 finalPtWeights[i] += w;
01755 finalPtValues[i] += w*value;
01756 }
01757 }
01758 return;
01759 }
01760
01761 void QCAD::SaddleValueResponseFunction::
01762 accumulatePointData(const double* p, double value, double* grad)
01763 {
01764 vFieldValues.push_back(value);
01765 vCoords.push_back( QCAD::maxDimPt(p,numDims) );
01766 vGrads.push_back( QCAD::maxDimPt(grad,numDims) );
01767 }
01768
01769
01770 void QCAD::SaddleValueResponseFunction::
01771 accumulateLevelSetData(const double* p, double value, double cellArea)
01772 {
01773 vlsFieldValues.push_back(value);
01774 vlsCellAreas.push_back(cellArea);
01775 for(std::size_t i=0; i < numDims; ++i)
01776 vlsCoords[i].push_back(p[i]);
01777 }
01778
01779
01780
01781 double QCAD::SaddleValueResponseFunction::
01782 getSaddlePointWeight(const double* p) const
01783 {
01784 return pointFn(imagePts[iSaddlePt].coords.distanceTo(p) , imagePts[iSaddlePt].radius );
01785 }
01786
01787 double QCAD::SaddleValueResponseFunction::
01788 getTotalSaddlePointWeight() const
01789 {
01790 return imagePts[iSaddlePt].weight;
01791 }
01792
01793 const double* QCAD::SaddleValueResponseFunction::
01794 getSaddlePointPosition() const
01795 {
01796 return imagePts[iSaddlePt].coords.data();
01797 }
01798
01799 bool QCAD::SaddleValueResponseFunction::
01800 matchesCurrentResults(Epetra_Vector& g) const
01801 {
01802 const double TOL = 1e-8;
01803
01804 if(iSaddlePt < 0) return false;
01805
01806 if( fabs(g[0] - returnFieldVal) > TOL || fabs(g[1] - imagePts[iSaddlePt].value) > TOL)
01807 return false;
01808
01809 for(std::size_t i=0; i<numDims; i++) {
01810 if( fabs(g[2+i] - imagePts[iSaddlePt].coords[i]) > TOL ) return false;
01811 }
01812
01813 return true;
01814 }
01815
01816
01817 double QCAD::SaddleValueResponseFunction::
01818 pointFn(double d, double radius) const {
01819
01820
01821 const double N = 1.0;
01822 double val = N*exp(-d*d / (2*radius*radius));
01823 return (val >= 1e-2) ? val : 0.0;
01824 }
01825
01826 int QCAD::SaddleValueResponseFunction::
01827 getHighestPtIndex() const
01828 {
01829
01830 int iHighestPt = 0;
01831 for(std::size_t i=1; i<nImagePts; i++) {
01832 if(imagePts[i].value > imagePts[iHighestPt].value) iHighestPt = i;
01833 }
01834 return iHighestPt;
01835 }
01836
01837
01838
01839
01841
01842
01843
01844
01845
01846
01847
01848
01849
01850
01851
01852
01853
01854
01855
01856
01857
01858
01859
01860
01861
01862
01863
01864
01865
01866
01867
01868
01869 bool QCAD::ptInPolygon(const std::vector<QCAD::mathVector>& polygon, const QCAD::mathVector& pt)
01870 {
01871 return QCAD::ptInPolygon(polygon, pt.data());
01872 }
01873
01874 bool QCAD::ptInPolygon(const std::vector<QCAD::mathVector>& polygon, const double* pt)
01875 {
01876 bool c = false;
01877 int n = (int)polygon.size();
01878 double x=pt[0], y=pt[1];
01879 const int X=0,Y=1;
01880
01881 for (int i = 0, j = n-1; i < n; j = i++) {
01882 const QCAD::mathVector& pi = polygon[i];
01883 const QCAD::mathVector& pj = polygon[j];
01884 if ((((pi[Y] <= y) && (y < pj[Y])) ||
01885 ((pj[Y] <= y) && (y < pi[Y]))) &&
01886 (x < (pj[X] - pi[X]) * (y - pi[Y]) / (pj[Y] - pi[Y]) + pi[X]))
01887 c = !c;
01888 }
01889 return c;
01890 }
01891
01892
01893
01894
01895
01896
01897
01898
01899
01900
01901
01902
01903
01904
01905
01906
01907
01908
01909
01910
01911
01912
01913
01915
01916
01917 QCAD::mathVector::mathVector()
01918 {
01919 dim_ = -1;
01920 }
01921
01922 QCAD::mathVector::mathVector(int n)
01923 :data_(n)
01924 {
01925 dim_ = n;
01926 }
01927
01928
01929 QCAD::mathVector::mathVector(const mathVector& copy)
01930 {
01931 data_ = copy.data_;
01932 dim_ = copy.dim_;
01933 }
01934
01935 QCAD::mathVector::~mathVector()
01936 {
01937 }
01938
01939
01940 void
01941 QCAD::mathVector::resize(std::size_t n)
01942 {
01943 data_.resize(n);
01944 dim_ = n;
01945 }
01946
01947 void
01948 QCAD::mathVector::fill(double d)
01949 {
01950 for(int i=0; i<dim_; i++) data_[i] = d;
01951 }
01952
01953 void
01954 QCAD::mathVector::fill(const double* vec)
01955 {
01956 for(int i=0; i<dim_; i++) data_[i] = vec[i];
01957 }
01958
01959 double
01960 QCAD::mathVector::dot(const mathVector& v2) const
01961 {
01962 double d=0;
01963 for(int i=0; i<dim_; i++)
01964 d += data_[i] * v2[i];
01965 return d;
01966 }
01967
01968 QCAD::mathVector&
01969 QCAD::mathVector::operator=(const mathVector& rhs)
01970 {
01971 data_ = rhs.data_;
01972 dim_ = rhs.dim_;
01973 return *this;
01974 }
01975
01976 QCAD::mathVector
01977 QCAD::mathVector::operator+(const mathVector& v2) const
01978 {
01979 mathVector result(dim_);
01980 for(int i=0; i<dim_; i++) result[i] = data_[i] + v2[i];
01981 return result;
01982 }
01983
01984 QCAD::mathVector
01985 QCAD::mathVector::operator-(const mathVector& v2) const
01986 {
01987 mathVector result(dim_);
01988 for(int i=0; i<dim_; i++) result[i] = data_[i] - v2[i];
01989 return result;
01990 }
01991
01992 QCAD::mathVector
01993 QCAD::mathVector::operator*(double scale) const
01994 {
01995 mathVector result(dim_);
01996 for(int i=0; i<dim_; i++) result[i] = scale*data_[i];
01997 return result;
01998 }
01999
02000 QCAD::mathVector&
02001 QCAD::mathVector::operator+=(const mathVector& v2)
02002 {
02003 for(int i=0; i<dim_; i++) data_[i] += v2[i];
02004 return *this;
02005 }
02006
02007 QCAD::mathVector&
02008 QCAD::mathVector::operator-=(const mathVector& v2)
02009 {
02010 for(int i=0; i<dim_; i++) data_[i] -= v2[i];
02011 return *this;
02012 }
02013
02014 QCAD::mathVector&
02015 QCAD::mathVector::operator*=(double scale)
02016 {
02017 for(int i=0; i<dim_; i++) data_[i] *= scale;
02018 return *this;
02019 }
02020
02021 QCAD::mathVector&
02022 QCAD::mathVector::operator/=(double scale)
02023 {
02024 for(int i=0; i<dim_; i++) data_[i] /= scale;
02025 return *this;
02026 }
02027
02028 double&
02029 QCAD::mathVector::operator[](int i)
02030 {
02031 return data_[i];
02032 }
02033
02034 const double&
02035 QCAD::mathVector::operator[](int i) const
02036 {
02037 return data_[i];
02038 }
02039
02040 double
02041 QCAD::mathVector::distanceTo(const mathVector& v2) const
02042 {
02043 double d = 0.0;
02044 for(int i=0; i<dim_; i++) d += pow(data_[i]-v2[i],2);
02045 return sqrt(d);
02046 }
02047
02048 double
02049 QCAD::mathVector::distanceTo(const double* p) const
02050 {
02051 double d = 0.0;
02052 for(int i=0; i<dim_; i++) d += pow(data_[i]-p[i],2);
02053 return sqrt(d);
02054 }
02055
02056 double
02057 QCAD::mathVector::norm() const
02058 {
02059 return sqrt(dot(*this));
02060 }
02061
02062 double
02063 QCAD::mathVector::norm2() const
02064 {
02065 return dot(*this);
02066 }
02067
02068
02069 void
02070 QCAD::mathVector::normalize()
02071 {
02072 (*this) /= norm();
02073 }
02074
02075 const double*
02076 QCAD::mathVector::data() const
02077 {
02078 return data_.data();
02079 }
02080
02081 double*
02082 QCAD::mathVector::data()
02083 {
02084 return data_.data();
02085 }
02086
02087
02088 std::size_t
02089 QCAD::mathVector::size() const
02090 {
02091 return dim_;
02092 }
02093
02094 std::ostream& QCAD::operator<<(std::ostream& os, const QCAD::mathVector& mv)
02095 {
02096 std::size_t size = mv.size();
02097 os << "(";
02098 for(std::size_t i=0; i<size-1; i++) os << mv[i] << ", ";
02099 if(size > 0) os << mv[size-1];
02100 os << ")";
02101 return os;
02102 }
02103
02104 std::ostream& QCAD::operator<<(std::ostream& os, const QCAD::nebImagePt& np)
02105 {
02106 os << std::endl;
02107 os << "coords = " << np.coords << std::endl;
02108 os << "veloc = " << np.velocity << std::endl;
02109 os << "grad = " << np.grad << std::endl;
02110 os << "value = " << np.value << std::endl;
02111 os << "weight = " << np.weight << std::endl;
02112 return os;
02113 }
02114
02115
02116
02117
02119
02120
02121 void QCAD::gatherVector(std::vector<double>& v, std::vector<double>& gv, const Epetra_Comm& comm_)
02122 {
02123 double *pvec, zeroSizeDummy = 0;
02124 pvec = (v.size() > 0) ? &v[0] : &zeroSizeDummy;
02125
02126 Epetra_Map map(-1, v.size(), 0, comm_);
02127 Epetra_Vector ev(View, map, pvec);
02128 int N = map.NumGlobalElements();
02129 Epetra_LocalMap lomap(N,0,comm_);
02130
02131 gv.resize(N);
02132 pvec = (gv.size() > 0) ? &gv[0] : &zeroSizeDummy;
02133 Epetra_Vector egv(View, lomap, pvec);
02134 Epetra_Import import(lomap,map);
02135 egv.Import(ev, import, Insert);
02136 }
02137
02138 bool QCAD::lessOp(std::pair<std::size_t, double> const& a,
02139 std::pair<std::size_t, double> const& b) {
02140 return a.second < b.second;
02141 }
02142
02143 void QCAD::getOrdering(const std::vector<double>& v, std::vector<int>& ordering)
02144 {
02145 typedef std::vector<double>::const_iterator dbl_iter;
02146 typedef std::vector<std::pair<std::size_t, double> >::const_iterator pair_iter;
02147 std::vector<std::pair<std::size_t, double> > vPairs(v.size());
02148
02149 size_t n = 0;
02150 for (dbl_iter it = v.begin(); it != v.end(); ++it, ++n)
02151 vPairs[n] = std::make_pair(n, *it);
02152
02153
02154 std::sort(vPairs.begin(), vPairs.end(), QCAD::lessOp);
02155
02156 ordering.resize(v.size()); n = 0;
02157 for (pair_iter it = vPairs.begin(); it != vPairs.end(); ++it, ++n)
02158 ordering[n] = it->first;
02159 }
02160
02161
02162 double QCAD::averageOfVector(const std::vector<double>& v)
02163 {
02164 double avg = 0.0;
02165 for(std::size_t i=0; i < v.size(); i++) {
02166 avg += v[i];
02167 }
02168 avg /= v.size();
02169 return avg;
02170 }
02171
02172 double QCAD::distance(const std::vector<double>* vCoords, int ind1, int ind2, std::size_t nDims)
02173 {
02174 double d2 = 0;
02175 for(std::size_t k=0; k<nDims; k++)
02176 d2 += pow( vCoords[k][ind1] - vCoords[k][ind2], 2 );
02177 return sqrt(d2);
02178 }