import java.awt.*; /** * Each instance is a cell within a cellular autonome. * This class describes the properties of each cell. */ public class Cell11 { // Autonimic cell /** * Column, row position number */ private int i, j; /** * Array of nearest neighbours cell ids */ public int [] neighbour; /** * Cell stress variable */ public double cellStress; /** * Variable for aligning cells correctly in the visual display */ private static int yShift=0; /** * Lattice dimension (Number of cells along each axis) * Number of neighbouring cells */ private static int Nx, neighbourNumber; /** * Stress conservation factor * The maximum cell strength * The mimimum cell strength */ private static double beta, maxStrength, minStrength; private static double relaxFactor; /** * Rupture threshold */ public double ruptureStress; /** * Stress to be passed onto adjacent cells */ public double overFlowStress; /** * Question: Has cell ruptured during this timestep? */ public boolean isRuptured; /** * Question: Use peroiodic boundary conditions? */ public static boolean usePeriodicBC; /** * Question: Use assymetric redistribution rule? */ public static boolean useAsymmetric; /** * The Cell object with a unique (x,y) position in a lattice * @param newI The x lattice position * @param newJ The y lattice position */ // public Cell11(int i, int j, int Nx, double maxStrength, double minStrength, double beta, boolean usePeriodicBC, double maxRelaxStressFactor) { public Cell11(int newI, int newJ) { setRandomRuptureStress(maxStrength, minStrength) ; cellStress = ruptureStress * Math.random(); isRuptured = false; i = newI; j = newJ; neighbour = new int [neighbourNumber]; int n = i + j * Nx ; if(neighbourNumber==4){generateSquareLatticeNeighbours();} if(neighbourNumber==6){generateHexagonalLatticeNeighbours();} } /** * Fills the neighbour id array for a square lattice with open, periodic or assymmetric BC */ private void generateSquareLatticeNeighbours(){ if( usePeriodicBC ) { if (i+1-1) {neighbour[1] = (i-1) + j * Nx;} else { neighbour[1] = Nx - 1 + j*Nx ;} if (j+1-1) {neighbour[3] = i + (j-1) * Nx;} else { neighbour[3] = Nx*(Nx-1) + i ;} } else{ if (i+1-1) {neighbour[1] = (i-1) + j * Nx;} else { neighbour[1] = -1;} if (j+1-1) {neighbour[3] = i + (j-1) * Nx;} else { neighbour[3] = -1;} } if( useAsymmetric){ if (i+1-1) {neighbour[1] = (i-1) + j * Nx;} else { neighbour[1] = Nx - 1 + j*Nx ;} if (j+1-1) {neighbour[3] = i + (j-1) * Nx;} else { neighbour[3] = -1;} } } /** * Sets the static runtime parameters * For next run use: * @param newNx Lattice dimension (Number of cells along each axis) * @param newMaxStrength Maximum cell strength * @param newMinStrength Minimum cell strength * @param newBeta Conservation factor * @param newUsePeriodicBC Question: Use periodic BC? * @param newMaxRelaxStressFactor Percentage range over which the stress is to be reset above zero */ public static void setAutonomeCellParameters(int newNx, int newNeighbourNumber, double newMaxStrength, double newMinStrength, double newBeta, boolean newUsePeriodicBC, double newMaxRelaxStressFactor){ usePeriodicBC = newUsePeriodicBC; maxStrength = newMaxStrength; minStrength = newMinStrength; Nx = newNx; beta = newBeta; relaxFactor = newMaxRelaxStressFactor; useAsymmetric = false; neighbourNumber = newNeighbourNumber; } /** * Fills the neighbour id array for a hexagonbal lattice with open or periodic BC */ private void generateHexagonalLatticeNeighbours(){ boolean evenI; double iTest1 = i/2; double iTest2 = Math.floor(i/2); if(iTest1==iTest2){ evenI = true; } else { evenI = false; } if( usePeriodicBC ) { if (i+1-1) {neighbour[1] = (i-1) + j * Nx;} else { neighbour[1] = Nx - 1 + j*Nx ;} if (j+1-1) {neighbour[3] = i + (j-1) * Nx;} else { neighbour[3] = Nx*(Nx-1) + i ;} if (evenI){ if (i+1>-1) { neighbour[4] = i + 1 - Nx ; neighbour[5] = i - 1 - Nx; } else { neighbour[5] = Nx*(Nx-1) + i - 1; neighbour[4] = Nx*(Nx-1) + i + 1; } } else{ if (i+1>Nx) { neighbour[4] = i + 1 + Nx ; neighbour[5] = i - 1 + Nx; } else { neighbour[5] = i + 1 ; neighbour[4] = i - 1; } } } else{ if (i+1-1) {neighbour[1] = (i-1) + j * Nx;} else { neighbour[1] = -1;} if (j+1-1) {neighbour[3] = i + (j-1) * Nx;} else { neighbour[3] = -1;} if (evenI){ if (i-1>-1) { neighbour[4] = i + 1 - Nx ; neighbour[5] = i - 1 - Nx; } else { neighbour[5] = -1; neighbour[4] = -1; } } else{ if (i+1>Nx) { neighbour[4] = i + 1 + Nx ; neighbour[5] = i - 1 + Nx; } else { neighbour[5] = -1; neighbour[4] = -1; } } } } /** * Method to reset the cell as being not ruptured */ public void setCellNotRuptured() { isRuptured = false; } /** * Increment the cells stress using arguments * @param stressIncrement Value to increment stress by * @param percentageNoise */ public void incrementStress(double stressIncrement, double percentageNoise) { double randomNoise = 0.5 - Math.random(); double stressIncrementNoise = percentageNoise * stressIncrement * randomNoise; cellStress += stressIncrement + stressIncrementNoise; } /** * Returns the overflow stress for that cell */ public double getOverFlowStress() { return overFlowStress; } /** * Sets isRuptured true for this timestep */ public double getProximityToFailure() {return (ruptureStress - cellStress); } /** * Returns the cell stress */ public double getCellStress() { return cellStress; } /** * Returns the cell strength */ public double getCellStrength() { return ruptureStress; } /** * * @param overFlowStressIncrement */ public void propagateStress(double overFlowStressIncrement) { if( isRuptured == false ){ cellStress += overFlowStressIncrement; } } public void initiateRupture() { isRuptured = true; // stressReleaseFactor determines the fraction of stress released in a rupture double stressReleaseFactor = 1 - relaxFactor * Math.random(); overFlowStress = cellStress * beta * stressReleaseFactor; // the cell stress is then the original stress times the stress not released cellStress = -10 + cellStress * (1-stressReleaseFactor); } /** * * @return */ public boolean isCellStressFlagged() { return cellStress < 0; } public void setCellStressZero() { cellStress = cellStress + 10 ; } public boolean isStressAboveThreshold() { return cellStress > ruptureStress; } public boolean isCellRuptured() { return isRuptured; } /** * Returns the ith neighbour * @return the ith neighbour * @param i the ith of 4 neighbours */ public int getNeighbour(int i) { return neighbour[i] ;} /** * Sets the initial cell strength between the limits minStrength and maxStrength * @param minStrength The lower limit for the random strength allocation * @param maxStrength The upper limit for the random strength allocation */ private void setRandomRuptureStress(double maxStrength, double minStrength) { ruptureStress = minStrength + ( maxStrength - minStrength ) * Math.random(); } /** * Method describing how top draw a cell * @param g2 * @param type * @param xOffset * @param yOffset * @param cellWidth Width to draw cell */ public void paint(Graphics g2, int type, int cellWidth, int xOffset, int yOffset) { int cellColor = 0; if(type==1){ cellColor = (int) (255 * cellStress); if(cellColor<1) {g2.setColor(new Color( 255,255, 255));} else if(isRuptured==true) {g2.setColor(new Color( 255,255, 255));} else if(cellColor>255) {g2.setColor(new Color( 111,111, 0));} else {g2.setColor(new Color(0, 0, cellColor));} } if (type==2){ cellColor = (int) (255 * ruptureStress); if(cellColor<1){g2.setColor(new Color( 0,111, 0));} else if(cellColor>255){g2.setColor(new Color( 111,111, 0));} else{g2.setColor(new Color(0, cellColor, 0));} } if (type==3){ cellColor = (int) (255 * (-cellStress + ruptureStress)); if(cellColor<1){g2.setColor(new Color( 255,255, 255));} else if(cellColor>255){g2.setColor(new Color( 111,111, 0));} else{g2.setColor(new Color(cellColor, 0, 0));} } if(neighbourNumber==4){g2.fillRect( (int) (i-1)*cellWidth + xOffset, (int) (j-1)*cellWidth + yOffset, cellWidth, cellWidth);} if(neighbourNumber==6){ if(yShift==1){ yShift=0; } else { yShift=1; } int dx = xOffset + 2 * (i-1); int dy = yOffset + 2 * (j-1) + yShift; int x[] = {1 + dx,2 + dx,3 + dx,2 + dx,1 + dx,0 + dx}; int y[] = {0 + dy,0 + dy,1 + dy,2 + dy,2 + dy,1 + dy}; g2.fillPolygon( x, y, 6 ); } } }