/* * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOUSE. See the GNU * General Public License for more details. * * You should have recieved a copy of the GNU General Public License * along with this program; if not write to the Free Software * Foundation, inc., 59 Temple Place, Suite 330, Boston MA 02111-1307 * USA */ package run; import java.util.*; import java.io.*; import java.nio.channels.*; import run.readers.FembicReader; import jp.sync.*; /** * Solver SMP * * @author Jonas Forssell, Yuriy Mikhaylovskiy * */ public class ModelSmp implements Runnable, ExceptionListener { private volatile double time,ttemp; private double timestep; private boolean autostep; private boolean failure_is_set = false; private int number_of_elements; private int number_of_trackers; private int number_of_nodes; private int number_of_materials; private int number_of_controls; private int number_of_groups; private int number_of_constraints; private int number_of_loads; private int nr_of_CPUs; private String filename; private Hashtable nodetable; private RplVector nodelist; private RplVector elementlist; private RplVector trackerlist; private RplVector materiallist; private RplVector constraintlist; private RplVector loadlist; private Controlset controlset; private int i; private Element temporary_element; private Tracker temporary_tracker; private Constraint temporary_constraint; private Node temporary_node; private Writer resultwriter; private TrackWriter trackwriter; private Thread[] tsolve; private Worker[] worker; private Set exception_listeners; private double timestep_error = Double.MAX_VALUE; /** * ModelSmp constructor comment. */ public ModelSmp(int nr_of_CPUs, String fname) { super(); this.nr_of_CPUs = nr_of_CPUs; exception_listeners = Collections.synchronizedSet(new HashSet()); this.filename = fname; } /** * Assemble Mass Matrix */ public void assembleMassMatrix() throws Exception { int i; Node temp_node; Element temp_element; Constraint temp_constraint; // Loop elements // Calculate element mass distribution and add to node // Calculate element intertia // Transform to global directions // Add to node inertia matrix // End loop try { System.out.println("Assembling Elements"); for (i = 0; i < number_of_elements; i++) { temp_element = (Element) elementlist.elementAt(i); temp_element.assembleMassMatrix(); } } catch (ArrayIndexOutOfBoundsException e) { throw new ArrayIndexOutOfBoundsException( "\n* Error during Assembly phase - Terminating" + e ); } catch (NullPointerException e) { throw new NullPointerException( "\n* Error during Assembly phase of Element\n* This error could be the result of a missing (or wrong) parameter in the indata file \n* " + e ); } // Loop nodes // Calculate main inertias // Keep largest I // End loop try { System.out.println("Assembling Nodes"); for (i = 0; i < nodelist.size(); i++) { temp_node = (Node) nodelist.elementAt(i); temp_node.determineMassMatrix(); } } catch (ArrayIndexOutOfBoundsException e) { throw new ArrayIndexOutOfBoundsException( "\n* Error during Assembly phase - Terminating" + e ); } catch (NullPointerException e) { throw new NullPointerException( "\n* Error during Assembly phase of Node \n* This error could be the result of a missing (or wrong) parameter in the indata file \n* " + e ); } try { System.out.println("Assembling Constraints"); for (i = 0; i < number_of_constraints; i++) { temp_constraint = (Constraint) constraintlist.elementAt(i); temp_constraint.determineMassMatrix(nodelist); } } catch (ArrayIndexOutOfBoundsException e) { throw new ArrayIndexOutOfBoundsException( "\n* Error during Assembly phase - Terminating" + e ); } catch (NullPointerException e) { throw new NullPointerException( "\n* Error during Assembly phase of Constraint \n* This error could be the result of a missing (or wrong) parameter in the indata file \n* " + e ); } } /** * This method initializes the problem in the following steps: * 1. Create a file object so that the indata file can be read. * 2. Question the file object of all the variables etc that is required to set up all the * memory variables etc correctly. * 3. Set up the variables * 4. Finished * * @param filename java.lang.String */ public void initialize(String fname) throws Exception { double frac, frac2; filename = new String(fname); // Create an indata file object that we can ask for the things we require Reader indatafile = new FembicReader(filename); // Set number of elements, materials and nodes number_of_elements = indatafile.numberOfElements(); number_of_trackers = indatafile.numberOfTrackers(); number_of_materials = indatafile.numberOfMaterials(); number_of_nodes = indatafile.numberOfNodes(); number_of_constraints = indatafile.numberOfConstraints(); number_of_loads = indatafile.numberOfLoads(); number_of_controls = indatafile.numberOfControls(); number_of_groups = indatafile.numberOfGroups(); //Set up the arrays to handle the entries elementlist = new RplVector(number_of_elements); trackerlist = new RplVector(number_of_trackers); materiallist = new RplVector(number_of_materials); nodelist = new RplVector(number_of_nodes); nodetable = new Hashtable(number_of_nodes); constraintlist = new RplVector(number_of_constraints); loadlist = new RplVector(number_of_loads); controlset = new Controlset(); //grouplist = new RplVector(number_of_groups); try { //Fill the constraintlist array System.out.println("Reading Constraints"); indatafile.open(); for (i = 0; i < number_of_constraints; i++) { constraintlist.addElement( indatafile.getNextConstraint(nodelist) ); } indatafile.close(); System.out.println("Filled constraintlist"); //Fill the loadlist array System.out.println("Reading Loads"); indatafile.open(); for (i = 0; i < number_of_loads; i++) { loadlist.addElement(indatafile.getNextLoad(nodelist)); } indatafile.close(); System.out.println("Filled loadlist"); //Fill the nodelist array indatafile.open(); System.out.println("Reading Nodes"); frac2 = 0; for (i = 0; i < number_of_nodes; i++) { temporary_node = indatafile.getNextNode(constraintlist, loadlist); nodelist.addElement(temporary_node); nodetable.put(new Integer(temporary_node.getNumber()), temporary_node); frac = i*10 / number_of_nodes; frac %= 10; if (frac != frac2) { System.out.println("" + 10*frac + "% complete"); frac2 = frac; } } indatafile.close(); System.out.println("Filled nodelist"); //Fill the materials array indatafile.open(); System.out.println("Reading Materials"); Material m; for (i = 0; i < number_of_materials; i++) { m = indatafile.getNextMaterial(); if (m.failure_strain_is_set || m.failure_stress_is_set) { failure_is_set = true; } materiallist.addElement(m); } indatafile.close(); System.out.println("Filled materiallist"); //Fill the Elements array indatafile.open(); System.out.println("Reading Elements"); frac2 = 0; for (i = 0; i < number_of_elements; i++) { elementlist.addElement(indatafile.getNextElement(materiallist, nodelist, loadlist, nodetable)); frac = i*10 / number_of_elements; frac %= 10; if (frac != frac2) { System.out.println("" + 10*frac + "% complete"); frac2 = frac; } } indatafile.close(); System.out.println("Filled elementlist"); //Fill the Trackers array indatafile.open(); System.out.println("Reading Trackers"); for (i = 0; i < number_of_trackers; i++) { trackerlist.addElement( indatafile.getNextTracker(nodelist, elementlist) ); } indatafile.close(); System.out.println("Filled trackerlist"); // Fill the grouplist array /* * Here, the grouplist could be filled. */ //Get the controlset indatafile.open(); System.out.println("Reading Controls"); for (i = 0; i < number_of_controls; i++) { indatafile.getControlSet(controlset); } indatafile.close(); System.out.println("Filled controlset"); // Create an outdata file that will print the results in the format we wish resultwriter = indatafile.getWriter(nodelist, elementlist, controlset, null); // Create a trackwriter that will print all trackresults in right format trackwriter = indatafile.getTrackWriter(trackerlist, controlset, null); } catch (java.text.ParseException e) { // If we end up here, something is wrong in the indata file, reading the parameters throw new java.text.ParseException("Parameter error in indata file \n" + e + " in line " + e.getErrorOffset(), e.getErrorOffset() ); } //Initialize the writer try { resultwriter.initialize(); } catch (Exception e) { throw new Exception("Initialization error of writer" + e,e); } //Initialize the trackwriter try { trackwriter.initialize(); } catch (Exception e) { throw new Exception("Initialization error of trackwriter" + e,e); } } /** * Insert the method's description here. Creation date: (2001-08-20 * 22:03:57) */ public void post() { } /** * This method prints the requested state of the solution to a file The * file will be called the same name as the indatafile, but with an ending * of *.res */ private void print() { System.out.println(); System.out.println(); System.out.println("time:" + time); try { resultwriter.write(filename, time); trackwriter.write(time); } catch (IOException ioe) { System.out.println(ioe); return; } } /** * Insert the method's description here. Creation date: (2001-08-20 * 22:03:07) */ public void setInitialConditions() { int i; int j; Node temp_node; Node neighbour_node; Element temp_element; Tracker temp_tracker; Constraint temp_constraint; double total_mass; // Initialize all the nodes System.out.println("Initializing nodes"); for (i = 0; i < nodelist.size(); i++) { temp_node = (Node) nodelist.elementAt(i); temp_node.setInitialConditions(); } /* * Sort the nodes in ascending x-coordinate order. */ System.out.println("Sorting nodes"); Collections.sort(nodelist,new NodeComparator()); /* * Set up the neighbour pointers needed for contact algorithm * Give each node a handle to it's neighbour */ System.out.println("Setting up node neighbour handles"); for (j = 0; j < nodelist.size(); j++) { temp_node = (Node) nodelist.elementAt(j); if (j < (nodelist.size() - 1)) { temp_node.setRight_neighbour((Node) nodelist.elementAt(j + 1)); } if (j > 0) { temp_node.setLeft_neighbour((Node) nodelist.elementAt(j - 1)); } } // Assigning nodes to a CPU System.out.println("Determining optimal model distribution for nodes"); // First get leftmost node temp_node = (Node) nodelist.firstElement(); while (temp_node.getLeft_neighbour() != null) temp_node = temp_node.getLeft_neighbour(); // Now, assign in increasing x-coordinate to CPU for (i = 0; i < nodelist.size(); i++) { temp_node.setCpu_number(i*nr_of_CPUs/nodelist.size()); temp_node = temp_node.getRight_neighbour(); } // Initialize all the elements System.out.println("Initializing elements"); for (i = 0; i < number_of_elements; i++) { temp_element = (Element) elementlist.elementAt(i); temp_element.setInitialConditions(); } // Assign each element to a CPU System.out.println("Assigning each element to a CPU"); for (i = 0; i < number_of_elements; i++) { temp_element = (Element) elementlist.elementAt(i); temp_element.determineCpu_number(); } // Initialize all the trackers System.out.println("Initializing trackers"); for (i = 0; i < number_of_trackers; i++) { temp_tracker = (Tracker) trackerlist.elementAt(i); temp_tracker.setInitialConditions(); } // Initialize all the constraints System.out.println("Initializing constraints"); for (i = 0; i < number_of_constraints; i++) { temp_constraint = (Constraint) constraintlist.elementAt(i); temp_constraint.setInitialConditions(); } // Initialize the controlset controlset.setInitialConditions(); // Now, if autostep is used, loop through all elements and determine the smallest timestep System.out.println("Determining smallest timestep size"); if (controlset.getTimestep(0) == 0) { timestep = 1E10; autostep = true; for (i = 0; i < number_of_elements; i++) { timestep = ((Element) elementlist.elementAt(i)).checkTimestep(timestep); } } else { timestep = controlset.getTimestep(0); autostep = false; } System.out.println("Determined timestep: " + timestep); // Sum up total model mass and print System.out.println("Calculating total model mass"); total_mass = 0; for (i = 0; i < nodelist.size(); i++) { temp_node = (Node) nodelist.elementAt(i); total_mass += temp_node.getMass(); } System.out.println("Total model mass = " + total_mass); } /** * This is the main loop of the program. Here, the solution is conducted. */ public void solve() throws InterruptedException { long time_info; long time_info_tmp; long time_remained; int time_h; int time_m; int time_s; String time_str; final Barrier barrier; boolean autosave = false; time_info = new Date().getTime(); ttemp = 1E10; // Set up an array of processes to distribute on each CPU tsolve = new Thread[nr_of_CPUs]; worker = new Worker[nr_of_CPUs]; int worker_element[] = new int[nr_of_CPUs]; int worker_node[] = new int[nr_of_CPUs]; barrier = BarrierFactory.createBarrier(nr_of_CPUs+1); // These threads represent a subset of the work done in the main thread. // Over time, most of the processes will be parallel time = controlset.getStarttime(); readAutoSave(); readAutoSaveError(); //Create workers and threads for(i=0; itimestep_error) timestep = timestep_error; autostep = false; } // Check if it is time to print something if (controlset.timeToPrint(time)) { System.out.println(); System.out.println(); time_info_tmp = new Date().getTime(); time_remained = (((time_info_tmp - time_info) * ((int) ((controlset.getEndtime() - time) / controlset.getPrintstep()))) / 1000); time_h = (int) (time_remained / 3600); time_m = (int) ((time_remained / 60) - (time_h * 60)); time_s = (int) (time_remained - (((int) (time_remained / 60)) * 60)); time_str = ""; if (time_h < 10) { time_str += ("0" + time_h); } else { time_str += time_h; } if (time_m < 10) { time_str += (":0" + time_m); } else { time_str += (":" + time_m); } if (time_s < 10) { time_str += (":0" + time_s); } else { time_str += (":" + time_s); } System.out.println("Time: " + time + "\tRemaining time (hh:mm:ss) " + time_str); time_info = time_info_tmp; try { resultwriter.write(filename, time); autosave = true; } catch (IOException ioe) { System.out.println(ioe); return; } } // Check if it is time to print something on the trackers if (controlset.timeToPrintTracker(time)) { trackwriter.write(time); } barrier.sync(); // *********** Worker *************** // Loop Nodes again to clear forces // ********************************** barrier.sync(); if (autosave){ writeAutoSave(); autosave = false; } } // Solution is finished correctly. Finish off the workers for (i = 0; i < nr_of_CPUs; i++) tsolve[i].interrupt(); // and end this solution this.post(); } /** * This is where we end up when a serious exception has occurred in the worker threads * */ public void exceptionOccurred(Exception e, Object o){ stopThreads(); // Pass this error on to the GUI sendException(e); } /** * This method sends an exception to registred listeners. * This is needed since exception migrates normally only to the run() method and not outside. * * @param e The exception to send */ private void sendException(Exception e) { if (exception_listeners.size() == 0) { e.printStackTrace(); return; } Iterator iter = exception_listeners.iterator(); while (iter.hasNext()) { ExceptionListener l = (ExceptionListener) iter.next(); l.exceptionOccurred(e,this); } if(!(e instanceof InterruptedException)) writeAutoSaveError(); } public void stopThreads() { for (int i=0 ; i < nr_of_CPUs; i++) if (tsolve != null && tsolve[i] != null) tsolve[i].interrupt(); for (int i=0 ; i < nr_of_CPUs; i++) { try { if (tsolve != null && tsolve[i] != null) tsolve[i].join(); } catch (InterruptedException e) { } } } /** * Add exception listener to the object * * @param l The listener to add */ public void addExceptionListener(ExceptionListener l) { exception_listeners.add(l); } public void run() { long stime; System.out.println("Processing file: " + filename); System.out.println("*** Initializing ***"); try { initialize(filename); if (Thread.currentThread().isInterrupted()) throw new InterruptedException(); // Assemble the mass matrix System.out.println("*** Assembling the Mass Matrix ***"); assembleMassMatrix(); if (Thread.currentThread().isInterrupted()) throw new InterruptedException(); // Set up the prerequisites System.out.println("*** Setting Initial Conditions ***"); setInitialConditions(); if (Thread.currentThread().isInterrupted()) throw new InterruptedException(); // Solve the problem stime = System.currentTimeMillis(); System.out.println("*** Initiating Solver ***"); solve(); } catch (Exception e) { stopThreads(); sendException(e); // Notify GUI return; } System.out.println("Solving took " + (System.currentTimeMillis() - stime) + " ms"); // Post the results and clean up post(); //Solution has ended successfully } // Auto save public void writeAutoSave(){ if(controlset.getRestoreSaveStatus()==Controlset.RESTORE_SAVE_OFF) return; try{ ObjectOutputStream aout = new ObjectOutputStream(new FileOutputStream(filename+".autosave")); writeObject(aout); aout.flush(); aout.close(); if(controlset.getRestoreSaveStatus()==Controlset.RESTORE_SAVE_PREVIOUS){ System.out.println("Auto Save Time: " + time + " ... ok"); System.out.println(new Date() + "\n"); return; }else{ FileChannel fain = new FileInputStream(filename+".autosave").getChannel(); FileChannel faout = new FileOutputStream(filename+".autosave."+time).getChannel(); fain.transferTo(0, fain.size(), faout); fain.close(); faout.close(); FileChannel frin = new FileInputStream(filename+".flavia.res").getChannel(); FileChannel frout = new FileOutputStream(filename+".flavia.res."+time).getChannel(); frin.transferTo(0, frin.size(), frout); frin.close(); frout.close(); for (i = 0; i < number_of_trackers; i++) { temporary_tracker = (Tracker) trackerlist.elementAt(i); FileChannel ftin = new FileInputStream(temporary_tracker.filename).getChannel(); FileChannel ftout = new FileOutputStream(temporary_tracker.filename+"."+time).getChannel(); ftin.transferTo(0, ftin.size(), ftout); ftin.close(); ftout.close(); } System.out.println("Auto Save Time: " + time + " ... ok"); System.out.println(new Date() + "\n"); } } catch (Exception e) {e.printStackTrace(); } } public void readAutoSave(){ if(controlset.getRestoreSaveStatus()==Controlset.RESTORE_SAVE_OFF || ! new File(filename+".autosave").exists() ) return; try{ ObjectInputStream ain = new ObjectInputStream(new FileInputStream(filename+".autosave")); readObject(ain); ain.close(); System.out.println("Found saved result for Time: " + time + "\tTime step: "+timestep); } catch (Exception e) {if(! (e instanceof FileNotFoundException)) e.printStackTrace(); } } private void writeObject(java.io.ObjectOutputStream out) throws IOException{ out.writeDouble(time); out.writeDouble(ttemp); out.writeDouble(timestep); out.writeBoolean(autostep); out.writeBoolean(failure_is_set); out.writeInt(number_of_elements); out.writeInt(number_of_trackers); out.writeInt(number_of_nodes); out.writeInt(number_of_materials); out.writeInt(number_of_controls); out.writeInt(number_of_groups); out.writeInt(number_of_constraints); out.writeInt(number_of_loads); out.writeInt(nr_of_CPUs); out.writeObject(filename); out.writeObject(nodetable); out.writeObject(nodelist); out.writeObject(elementlist); out.writeObject(trackerlist); out.writeObject(materiallist); out.writeObject(constraintlist); out.writeObject(loadlist); out.writeObject(controlset); out.writeObject(resultwriter); out.writeObject(trackwriter); } private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException{ time = in.readDouble(); ttemp = in.readDouble(); timestep = in.readDouble(); autostep = in.readBoolean(); failure_is_set = in.readBoolean(); number_of_elements = in.readInt(); number_of_trackers = in.readInt(); number_of_nodes = in.readInt(); number_of_materials = in.readInt(); number_of_controls = in.readInt(); number_of_groups = in.readInt(); number_of_constraints = in.readInt(); number_of_loads = in.readInt(); nr_of_CPUs = in.readInt(); filename = (String) in.readObject(); nodetable = (Hashtable) in.readObject(); nodelist = (RplVector) in.readObject(); elementlist = (RplVector) in.readObject(); trackerlist = (RplVector) in.readObject(); materiallist = (RplVector) in.readObject(); constraintlist = (RplVector) in.readObject(); loadlist = (RplVector) in.readObject(); controlset = (Controlset) in.readObject(); resultwriter = (Writer) in.readObject(); trackwriter = (TrackWriter) in.readObject(); } /* * At occurrence of an error calculation stops. * In a file error time, an error step are saved. * At restart of model time step decreases twice * ( timestep = timestep_error / 2 ). * So there is each time at model start. * It allows to define a step correctly. * * При возникновении ошибки расчет останавливается. * В файл сохранены время ошибки, шаг ошибки. * При повторном запуске модели шаг времени уменьшается в два раза * ( timestep = timestep_error / 2 ). * Так происходит каждый раз при запуске модели. * Это позволяет правильно определить шаг. */ public void writeAutoSaveError(){ if(controlset.getRestoreSaveStatus()==Controlset.RESTORE_SAVE_OFF) return; try{ String info = " At occurrence of an error calculation stops." +"\n In a file error time, an error step are saved." +"\n At restart of model time step decreases twice" +"\n ( timestep = timestep_error / 2 )." +"\n So there is each time at model start." +"\n It allows to define a step correctly.\n"; Properties prop = new Properties(); prop.setProperty("Time", time+""); prop.setProperty("TimeStep", timestep+""); prop.store(new FileOutputStream(filename+".error"), info); } catch (Exception e) {e.printStackTrace(); } } public void readAutoSaveError(){ if(controlset.getRestoreSaveStatus()==Controlset.RESTORE_SAVE_OFF || ! new File(filename+".error").exists() ) return; try{ Properties prop = new Properties(); prop.load(new FileInputStream(filename+".error")); timestep_error = Double.parseDouble(prop.getProperty("TimeStep")); System.out.println("Found saved error for Time: " + time + "\tTime step: "+timestep_error); timestep_error /= 2.0d; if(timestep>timestep_error) timestep = timestep_error; System.out.println("Changed time step: "+timestep_error); } catch (Exception e) {if(! (e instanceof FileNotFoundException)) e.printStackTrace(); } } }