static vumatptr load(const char* n){ typedef std::vector<VUMATPtrHandler> VUMATPtrContainer; static LibrariesHandler libraries; static VUMATPtrContainer fcts; #ifdef HAVE_STD_MUTEX static std::mutex m; std::lock_guard<std::mutex> lock(m); #else /* HAVE_STD_MUTEX */ lock l; #endif /* HAVE_STD_MUTEX */ try{ VUMATPtrContainer::const_iterator p; p = std::find_if(fcts.begin(),fcts.end(),VUMATNameCompare(n)); if(p==fcts.end()){ const std::pair<std::string,std::string> lf = decompose(n); const std::string& lib = lf.first; const std::string& fct = lf.second; if(lib.empty()){ report("","","",n); return NULLPTR(vumatptr); } #if (defined _WIN32 || defined _WIN64) && (!defined __CYGWIN__) libptr l = ::LoadLibrary(TEXT (lib.c_str())); #else libptr l = ::dlopen(lib.c_str(),RTLD_NOW); #endif if(l==NULLPTR(libptr)){ #if (defined _WIN32 || defined _WIN64) && (!defined __CYGWIN__) report(lib,"",getLastWin32Error(),n); #else report(lib,"",::dlerror(),n); #endif return NULLPTR(vumatptr); } libraries.insert(std::make_pair(lib,l)); union { void *ptr; vumatptr f; } r; #if (defined _WIN32 || defined _WIN64) && (!defined __CYGWIN__) r.f = reinterpret_cast<vumatptr>(::GetProcAddress(l,fct.c_str())); #else r.ptr = ::dlsym(l,fct.c_str()); #endif if(r.ptr==NULLPTR(void *)){ #if (defined _WIN32 || defined _WIN64) && (!defined __CYGWIN__) report(lib,fct,getLastWin32Error(),n); #else report(lib,fct,::dlerror(),n); #endif return NULLPTR(vumatptr); } VUMATPtrHandler h; h.name = std::string(n,n+80); h.ptr = r.f; fcts.push_back(h); return r.f; } return p->ptr; }
void evaluateGradient(struct configuration *p) { struct functionDefinition *fd; int i; double gradientCoordinate; NULLPTR(p); fd = p->functionDefinition; NULLPTR(fd); if (p->gradient == NULL) { p->gradient = (double *)allocate(sizeof(double) * fd->dimension); if (fd->dfunc == NULL) { evaluateGradientFromPotential(p); BAIL(); } else { (*fd->dfunc)(p); BAIL(); } fd->gradientEvaluationCount++; p->parameter = 0.0; p->maximumCoordinateInGradient = 0.0; for (i=fd->dimension-1; i>=0; i--) { CHECKNAN(p->gradient[i]); gradientCoordinate = fabs(p->gradient[i]); if (p->maximumCoordinateInGradient < gradientCoordinate) { p->maximumCoordinateInGradient = gradientCoordinate; } } } }
void evaluateGradientFromPotential(struct configuration *p) { struct functionDefinition *fd; struct configuration *pPlusDelta = NULL; struct configuration *pMinusDelta = NULL; int i; int j; NULLPTR(p); fd = p->functionDefinition; NULLPTR(fd); if (fd->gradient_delta == 0.0) { fd->gradient_delta = 1e-8; } for (i=0; i<fd->dimension; i++) { pPlusDelta = makeConfiguration(fd); for (j=0; j<fd->dimension; j++) { pPlusDelta->coordinate[j] = p->coordinate[j]; } pPlusDelta->coordinate[i] += fd->gradient_delta / 2.0; pMinusDelta = makeConfiguration(fd); for (j=0; j<fd->dimension; j++) { pMinusDelta->coordinate[j] = p->coordinate[j]; } pMinusDelta->coordinate[i] -= fd->gradient_delta / 2.0; p->gradient[i] = (evaluate(pMinusDelta) - evaluate(pPlusDelta)) / fd->gradient_delta; BAIL(); SetConfiguration(&pPlusDelta, NULL); SetConfiguration(&pMinusDelta, NULL); } }
void initializeFunctionDefinition(struct functionDefinition *fd, void (*func)(struct configuration *p), int dimension, int messageBufferLength) { NULLPTR(func); fd->func = func; fd->dfunc = NULL; fd->freeExtra = NULL; fd->termination = NULL; fd->constraints = NULL; fd->tolerance = 1e-8; fd->algorithm = PolakRibiereConjugateGradient; fd->linear_algorithm = LinearMinimize; fd->gradient_delta = 1e-8; fd->dimension = dimension; fd->initial_parameter_guess = 1.0; fd->parameter_limit = MAXDOUBLE; fd->functionEvaluationCount = 0; fd->gradientEvaluationCount = 0; if (messageBufferLength > 0) { fd->message = (char *)allocate(messageBufferLength); fd->message[0] = '\0'; fd->messageBufferLength = messageBufferLength; } else { fd->message = ""; fd->messageBufferLength = 0; } fd->allocationCount = 0; fd->freeCount = 0; fd->maxAllocation = 0; }
void oneDynamicsFrame(struct part *part, int iters, struct xyz *averagePositions, struct xyz **pOldPositions, struct xyz **pNewPositions, struct xyz **pPositions, struct xyz *force) { int j; int loop; double deltaTframe; struct xyz f; struct xyz *tmp; struct jig *jig; struct xyz *oldPositions = *pOldPositions; struct xyz *newPositions = *pNewPositions; struct xyz *positions = *pPositions; // wware 060109 python exception handling NULLPTR(part); NULLPTR(averagePositions); NULLPTR(oldPositions); NULLPTR(newPositions); NULLPTR(positions); iters = max(iters,1); deltaTframe = 1.0/iters; for (j=0; j<part->num_atoms; j++) { vsetc(averagePositions[j],0.0); } // See http://www.nanoengineer-1.net/mediawiki/index.php?title=Verlet_integration // for a discussion of how dynamics is done in the simulator. // we want: // x(t+dt) = 2x(t) - x(t-dt) + A dt^2 // or: // newPositions = 2 * positions - oldPositions + A dt^2 // wware 060110 don't handle Interrupted with the BAIL mechanism for (loop=0; loop < iters && !Interrupted; loop++) { _last_iteration = loop == iters - 1; Iteration++; // wware 060109 python exception handling updateVanDerWaals(part, NULL, positions); BAIL(); calculateGradient(part, positions, force); BAIL(); /* first, for each atom, find non-accelerated new pos */ /* Atom moved from oldPositions to positions last time, now we move it the same amount from positions to newPositions */ for (j=0; j<part->num_atoms; j++) { // f = positions - oldPositions vsub2(f,positions[j],oldPositions[j]); // newPositions = positions + f // or: // newPositions = 2 * positions - oldPositions vadd2(newPositions[j],positions[j],f); // after this, we will need to add A dt^2 to newPositions } // pre-force jigs for (j=0;j<part->num_jigs;j++) { /* for each jig */ jig = part->jigs[j]; // wware 060109 python exception handling NULLPTR(jig); switch (jig->type) { case LinearMotor: jigLinearMotor(jig, positions, newPositions, force, deltaTframe); break; default: break; } } /* convert forces to accelerations, giving new positions */ //FoundKE = 0.0; /* and add up total KE */ for (j=0; j<part->num_atoms; j++) { // to complete Verlet integration, this needs to do: // newPositions += A dt^2 // // force[] is in pN, mass is in g, Dt in seconds, f in pm vmul2c(f,force[j],part->atoms[j]->inverseMass); // inverseMass = Dt*Dt/mass // XXX: 0.15 probably needs a scaling by Dt // 0.15 = deltaX // keMax = m v^2 / 2 // v^2 = 2 keMax / m // v = deltaX / Dt = sqrt(2 keMax / m) // deltaX = Dt sqrt(2 keMax / m) // We probably don't want to do this, because a large raw // velocity isn't a problem, it's just when that creates a // high force between atoms that it becomes a problem. We // check that elsewhere. //if (!ExcessiveEnergyWarning && vlen(f)>0.15) { // 0.15 is just below H flyaway // WARNING3("Excessive force %.6f in iteration %d on atom %d -- further warnings suppressed", vlen(f), Iteration, j+1); // ExcessiveEnergyWarningThisFrame++; //} vadd(newPositions[j],f); //vsub2(f, newPositions[j], positions[j]); //ff = vdot(f, f); //FoundKE += atom[j].energ * ff; } // Jigs are executed in the following order: motors, // thermostats, grounds, measurements. Motions from each // motor are added together, then thermostats operate on the // motor output. Grounds override anything that moves atoms. // Measurements happen after all things that could affect // positions, including grounds. // motors for (j=0;j<part->num_jigs;j++) { /* for each jig */ jig = part->jigs[j]; if (jig->type == RotaryMotor) { jigMotor(jig, deltaTframe, positions, newPositions, force); } // LinearMotor handled in preforce above } // thermostats for (j=0;j<part->num_jigs;j++) { /* for each jig */ jig = part->jigs[j]; if (jig->type == Thermostat) { jigThermostat(jig, deltaTframe, positions, newPositions); } } // grounds for (j=0;j<part->num_jigs;j++) { /* for each jig */ jig = part->jigs[j]; if (jig->type == Ground) { jigGround(jig, deltaTframe, positions, newPositions, force); } } // measurements for (j=0;j<part->num_jigs;j++) { /* for each jig */ jig = part->jigs[j]; switch (jig->type) { case Thermometer: jigThermometer(jig, deltaTframe, positions, newPositions); break; case DihedralMeter: jigDihedral(jig, newPositions); break; case AngleMeter: jigAngle(jig, newPositions); break; case RadiusMeter: jigRadius(jig, newPositions); break; default: break; } } for (j=0; j<part->num_atoms; j++) { vadd(averagePositions[j],newPositions[j]); } tmp=oldPositions; oldPositions=positions; positions=newPositions; newPositions=tmp; if (ExcessiveEnergyWarningThisFrame > 0) { ExcessiveEnergyWarning = 1; } } for (j=0; j<part->num_atoms; j++) { vmulc(averagePositions[j],deltaTframe); } *pOldPositions = oldPositions; *pNewPositions = newPositions; *pPositions = positions; }