/** * This operation performs the tile updates needed by the generateTile() operation where * interfaces should be considered. * * @param tile the tile to update * @param slabM1 the slab one index less than (so above) the middle slab * @param slab the middle slab * @param dist the step distance */ private void updateTileByInterface( Tile tile, Slab slabM1, Slab slab, double zInt, double rufInt) { // Update the tile tile.thickness = zInt * slab.interfaceWidth; tile.scatteringLength = 0.5 * (slab.scatteringLength + slabM1.scatteringLength + rufInt * (slab.scatteringLength - slabM1.scatteringLength)); tile.trueAbsLength = 0.5 * (slab.trueAbsLength + slabM1.trueAbsLength + rufInt * (slab.trueAbsLength - slabM1.trueAbsLength)); tile.incAbsLength = 0.5 * (slab.incAbsLength + slabM1.incAbsLength + rufInt * (slab.incAbsLength - slabM1.incAbsLength)); return; }
/** * This operation performs the tile updates needed by the generateTile() operation. * * @param tile the tile to update * @param slabM1 the slab one index less than (so above) the middle slab * @param slab the middle slab * @param slabP1 the slab one index greater than (so below) the middle slab * @param dist the step distance * @throws MathException Thrown if the error function cannot be evaluated */ private void updateTileByLayer(Tile updateSlab, Slab slabM1, Slab slab, Slab slabP1, double dist) throws MathException { // Compute the exponentials double tExpFac = Erf.erf(cE * dist / slab.interfaceWidth); double bExpFac = Erf.erf(cE * (dist - slab.thickness) / (slabP1.interfaceWidth)); // Update the slab properties updateSlab.scatteringLength = getTileValue( slabM1.scatteringLength, slab.scatteringLength, slabP1.scatteringLength, tExpFac, bExpFac); updateSlab.trueAbsLength = getTileValue( slabM1.trueAbsLength, slab.trueAbsLength, slabP1.trueAbsLength, tExpFac, bExpFac); updateSlab.incAbsLength = getTileValue(slabM1.incAbsLength, slab.incAbsLength, slabP1.incAbsLength, tExpFac, bExpFac); return; }
/** * This operation generates a list of Tiles from the slabs with the corresponding number of * ordinate steps. * * @param slabs the slabs of materials that define the system * @param numRough the number of ordinate steps * @param zInt FIXME! This array must be preallocated with a size n = maxRoughSize. * @param rufInt FIXME! This array must be preallocated with a size n = maxRoughSize. * @return the system of generated tiles * @throws MathException Thrown if the error function cannot be calculated */ public Tile[] generateTiles(Slab[] slabs, int numRough, double[] zInt, double[] rufInt) throws MathException { // Local Declarations int nGlay = 0; double totalThickness = 0.0, gDMid = 0.0, step = 0.0, dist = 0.0; // The number of slabs was not defined in the original code. I computed // it by counting up the loops. This formula is currently off a little // bit. int numSlabs = 2 + 2 * (numRough / 2 + 1) + (slabs.length - 2) * (2 + numRough); Tile[] generatedSlabs = new Tile[numSlabs]; // Create the slabs for (int i = 0; i < numSlabs; i++) { generatedSlabs[i] = new Slab(); } // Evaluate the first half of the vacuum interface. Create the first // slab. Tile tmpSlab = generatedSlabs[0]; Slab refSlab = slabs[0], secondRefSlab = slabs[1], thirdRefSlab; tmpSlab.scatteringLength = refSlab.scatteringLength; tmpSlab.trueAbsLength = refSlab.trueAbsLength; tmpSlab.incAbsLength = refSlab.incAbsLength; tmpSlab.thickness = refSlab.thickness; ++nGlay; // Create the other slabs for this half for (int i = 0; i < numRough / 2 + 1; i++) { tmpSlab = generatedSlabs[nGlay + i]; updateTileByInterface(tmpSlab, refSlab, secondRefSlab, zInt[i], rufInt[i]); } nGlay += numRough / 2 + 1; // Evaluate the total normalized thickness of the surface for (int i = 0; i < numRough + 1; i++) { totalThickness += zInt[i]; } // Calculate gradation of layers. Using slabs.length - 1 because the // last layer is at index 4. for (int i = 1; i < slabs.length - 1; i++) { refSlab = slabs[i]; secondRefSlab = slabs[i + 1]; thirdRefSlab = slabs[i - 1]; // FIXME! Review gDMid calculation with John because it can be // negative. gDMid = refSlab.thickness - 0.5 * totalThickness * (refSlab.interfaceWidth + secondRefSlab.interfaceWidth); if (gDMid <= 1.0e-10) { // The interfaces are overlapping. Step through the entire slab step = refSlab.thickness / (numRough + 1); // Take the first half step tmpSlab = generatedSlabs[nGlay]; tmpSlab.thickness = step / 2.0; dist = step / 4.0; updateTileByLayer(tmpSlab, thirdRefSlab, refSlab, secondRefSlab, dist); ++nGlay; dist += 0.75 * step; // Take the remaining steps for (int j = 0; j < numRough; j++) { tmpSlab = generatedSlabs[nGlay + j]; tmpSlab.thickness = step; updateTileByLayer(tmpSlab, thirdRefSlab, refSlab, secondRefSlab, dist); dist += step; } nGlay += numRough; // Take final half step tmpSlab = generatedSlabs[nGlay]; tmpSlab.thickness = step / 2.0; dist = refSlab.thickness - step / 4.0; updateTileByLayer(tmpSlab, thirdRefSlab, refSlab, secondRefSlab, dist); ++nGlay; } else { // Evaluate contributions from interfaces separately. // Top interface for (int j = numRough / 2 + 1; j < numRough + 1; j++) { // Get the next slab and update it by considering the // interface contribution. tmpSlab = generatedSlabs[nGlay + j - numRough / 2 - 1]; updateTileByInterface(tmpSlab, thirdRefSlab, refSlab, zInt[j], rufInt[j]); } nGlay += numRough / 2 + 1; // Central, bulk-like portion tmpSlab = generatedSlabs[nGlay]; tmpSlab.scatteringLength = refSlab.scatteringLength; tmpSlab.thickness = gDMid; tmpSlab.trueAbsLength = refSlab.trueAbsLength; tmpSlab.incAbsLength = refSlab.incAbsLength; ++nGlay; // Bottom interface for (int j = 0; j < numRough / 2 + 1; j++) { tmpSlab = generatedSlabs[nGlay + j]; updateTileByInterface(tmpSlab, refSlab, secondRefSlab, zInt[j], rufInt[j]); } nGlay += numRough / 2 + 1; } } // Evaluate substrate gradation refSlab = slabs[slabs.length - 1]; secondRefSlab = slabs[slabs.length - 2]; for (int i = numRough / 2 + 1; i < numRough + 1; i++) { tmpSlab = generatedSlabs[nGlay + i - numRough / 2 - 1]; updateTileByInterface(tmpSlab, secondRefSlab, refSlab, zInt[i], rufInt[i]); } nGlay += numRough / 2 + 1; // Handle the last layer refSlab = slabs[slabs.length - 1]; tmpSlab = generatedSlabs[nGlay]; tmpSlab.scatteringLength = refSlab.scatteringLength; tmpSlab.trueAbsLength = refSlab.trueAbsLength; tmpSlab.incAbsLength = refSlab.incAbsLength; tmpSlab.thickness = refSlab.thickness; ++nGlay; return generatedSlabs; }