void traceJigHeader(struct part *part) { struct jig *j; int i; int ncol; __p = __line; __p += sprintf(__p, "# Time "); for (i=0; i<part->num_jigs; i++) { j = part->jigs[i]; j->data=0.0; j->data2=0.0; vsetc(j->xdata,0.0); switch (j->type) { case Ground: __p += sprintf(__p, "Anchor "); break; case Thermometer: __p += sprintf(__p, "T.meter "); break; case DihedralMeter: __p += sprintf(__p, "Dihedral "); break; case AngleMeter: __p += sprintf(__p, "Angle "); break; case RadiusMeter: __p += sprintf(__p, "Distance "); break; case Thermostat: __p += sprintf(__p, "T.stat "); break; case LinearMotor: __p += sprintf(__p, "Lmotor "); break; case RotaryMotor: __p += sprintf(__p, "speed torque "); } } sprintf(__p, "\n"); write_traceline(__line); __p = __line; __p += sprintf(__p, "# picosec "); for (i=0; i<part->num_jigs; i++) { j = part->jigs[i]; ncol = countOutputColumns(j); if (ncol > 0) { __p += sprintf(__p, " %-15.15s", j->name); while (ncol-- > 1) // 16 spaces __p += sprintf(__p, " %-15.15s", " "); } } if (PrintPotentialEnergy) { __p += sprintf(__p, " %-15.15s", "P.Energy"); __p += sprintf(__p, " %-15.15s", "K.Energy"); __p += sprintf(__p, " %-15.15s", "T.Energy"); } sprintf(__p, "\n"); write_traceline(__line); __p = __line; sprintf(__p, "#\n"); write_traceline(__line); }
void traceJigData(struct part *part, struct xyz *positions) { double x; int i; struct jig *j; __p = __line; __p += sprintf(__p, "%10.4f ", Iteration * Dt / PICOSEC); for (i=0; i<part->num_jigs; i++) { j = part->jigs[i]; switch (j->type) { case DihedralMeter: case AngleMeter: __p += sprintf(__p, " %15.5f", j->data); break; case Ground: x=vlen(j->xdata)/1e4; __p += sprintf(__p, " %15.2f", x / j->data); j->data=0.0; vsetc(j->xdata, 0.0); break; case RadiusMeter: case LinearMotor: // convert from picometers to angstroms __p += sprintf(__p, " %15.4f", 0.01 * j->data); j->data = 0.0; break; case Thermometer: case Thermostat: __p += sprintf(__p, " %15.2f", j->data); j->data = 0.0; break; case RotaryMotor: __p += sprintf(__p, " %15.3f %15.3f", j->data, j->data2); j->data = 0.0; j->data2 = 0.0; break; } } if (PrintPotentialEnergy) { double potential_energy = calculatePotential(part, positions); double kinetic_energy = calculateKinetic(part); __p += sprintf(__p, " %15.6f", potential_energy); __p += sprintf(__p, " %15.6f", kinetic_energy); __p += sprintf(__p, " %15.6f", potential_energy + kinetic_energy); } sprintf(__p, "\n"); // each snapshot is one line write_traceline(__line); }
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; }