package run;
import java.io.IOException;

import java.util.*;

import uka.karmi.rmi.RemoteException;

import jp.lang.*;

import jp.sync.Barrier;

import jp.sync.BarrierFactory;

public class Impact implements uka.patch.Patchable, uka.transport.Transportable {
   public void createPatch(Object _copy, uka.patch.PatchOutput po) throws java.io.IOException {
      Impact copy = (Impact)_copy;
   }
   public void applyPatch(Object _copy, uka.patch.PatchInput pi) throws java.io.IOException, ClassNotFoundException {
      Impact copy = (Impact)_copy;
   }
   public void descendReferences(uka.patch.ReferenceConsumer c) throws java.io.IOException {
   }
   public void filterReferences(uka.patch.ReferenceFilter f) {
   }
   public Object clone() {
      try {
         return super.clone();
      }  catch (CloneNotSupportedException ex) {
         throw new AssertionError("Declared Cloneable but clone() is still unsupported");
      }
   }
   public static final uka.transport.TransportDescriptor TRANSPORT_DESCRIPTOR = new uka.transport.TransportDescriptor(){
      public Object unmarshalReference(uka.transport.UnmarshalStream s, int id) throws java.io.IOException, ClassNotFoundException {
         return new Impact(s, id);
      }
      public boolean unmarshal(Object obj, uka.transport.UnmarshalStream s) throws ClassNotFoundException, java.io.IOException {
         ((Impact)obj).unmarshal(s);
         return false;
      }
      public void marshalReference(Object obj, uka.transport.MarshalStream s) throws java.io.IOException {
         ((Impact)obj).marshalReference(s);
      }
      public void marshal(Object obj, uka.transport.MarshalStream s) throws java.io.IOException {
         ((Impact)obj).marshal(s);
      }
      public Object deepClone(Object orig, int id, uka.transport.DeepClone _helper) throws CloneNotSupportedException {
         try {
            return new Impact((Impact)orig, id, _helper);
         }  catch (java.io.IOException ex) {
            throw (CloneNotSupportedException)new CloneNotSupportedException().initCause(ex);
         }
      }
      public boolean deepCloneReferences(Object orig, Object copy, uka.transport.DeepClone _helper) throws CloneNotSupportedException {
         ((Impact)copy).deepCloneReferences((Impact)orig, _helper);
         return false;
      }
      public Class getType() {
         return Impact.class;
      }
   };
   public uka.transport.TransportDescriptor getTransportDescriptor() {
      return TRANSPORT_DESCRIPTOR;
   }
   public Impact(uka.transport.UnmarshalStream _stream, int _id) throws java.io.IOException, ClassNotFoundException {
      _stream.register(this, _id);
   }
   public void unmarshal(uka.transport.UnmarshalStream _stream) throws java.io.IOException, ClassNotFoundException {
   }
   public void marshalReference(uka.transport.MarshalStream _stream) throws java.io.IOException {
   }
   public void marshal(uka.transport.MarshalStream _stream) throws java.io.IOException {
   }
   public Impact(Impact _orig, int _id, uka.transport.DeepClone _helper) throws CloneNotSupportedException, java.io.IOException {
      _helper.add(_id, this);
   }
   public void deepCloneReferences(Impact _orig, uka.transport.DeepClone _helper) throws CloneNotSupportedException {
   }
   public Impact() {
      super();
   }
   public static void main(java.lang.String[] args) {
      System.out.println("=========== Welcome to Impact ==========");
      System.out.println("= Impact is Alpha code. This means the =");
      System.out.println("= results are not validated and should =");
      System.out.println("= not be trusted for use.              =");
      System.out.println("=                                      =");
      System.out.println("= Impact is free software and licensed =");
      System.out.println("= under GPL. Please note that it comes =");
      System.out.println("= with no warranties whatsoever.       =");
      System.out.println("=                                      =");
      System.out.println("= Report any bugs at our webpage:      =");
      System.out.println("= http://impact.sourceforge.net        =");
      System.out.println("=============== ENJOY!!!! ==============\n\n");
      int nr_CPU = DistributedRuntime.getMachineCnt();
      if (args.length == 1) {
         if (nr_CPU > 0) try {
            run_cluster(args[0], nr_CPU);
         }  catch (Error e) {
            System.out.println(e);
            return;
         } catch (Exception e) {
            System.out.println(e);
            return;
         } else {
            nr_CPU = 1;
            try {
               run_smp(args[0], nr_CPU);
            }  catch (Error e) {
               System.out.println(e);
               return;
            } catch (RemoteException e) {
               e.printStackTrace();
            }
         }
      } else if (args.length == 2) {
         try {
            run_translator(args[0], args[1], nr_CPU);
         }  catch (Error e) {
            System.out.println(e);
            return;
         } catch (RemoteException e) {
            e.printStackTrace();
         }
      } else {
         System.out.println("Impact - A simple explicit dynamic program\n");
         System.out.println("Syntax: java run.Impact sourcefile.in  to start solver");
         System.out.println("Syntax: java run.Impact sourcefile.nas outfile.in to start translator");
      }
   }
   public static void run_smp(String fname, int nr_CPU) throws RemoteException, Error {
      System.out.println("*******************************");
      System.out.println("*** Solver has been invoked ***");
      System.out.println("*******************************\n\n");
      System.out.println("Running on " + nr_CPU + " clients\n\n");
      Smack smackinstance = new Smack(nr_CPU);
      System.out.println("Processing file: " + fname);
      System.out.println("*** Initializing ***");
      smackinstance.initialize(fname);
      System.out.println("*** Assembling the Mass Matrix ***");
      smackinstance.assembleMassMatrix();
      System.out.println("*** Setting Initial Conditions ***");
      smackinstance.setInitialConditions();
      long stime = System.currentTimeMillis();
      System.out.println("*** Initiating Solver ***");
      smackinstance.solve();
      System.out.println("Solving took " + (System.currentTimeMillis() - stime) + " ms");
      smackinstance.post();
   }
   public static void run_cluster(String fname, int nr_CPU) throws Exception {
      SmackCluster[] nodes;
      System.out.println("********************************");
      System.out.println("*** Cluster has been invoked ***");
      System.out.println("********************************\n\n");
      System.out.println("Running on " + nr_CPU + " clients\n\n");
      nodes = new SmackCluster[nr_CPU];
      System.out.println("*** Creating cluster processes ***");
      for (int n = 0; n < nr_CPU; n++) {
         nodes[n] =  /** @at n */ new SmackCluster(jp.lang.Node.getNode(n), nr_CPU, n);
      }
      System.out.println("*** Initialize primary process ***");
      nodes[0].initialize(fname, nodes);
      nodes[0].assembleMassMatrix();
      nodes[0].setInitialConditions();
      System.out.println("*** Pass references of replicated model ***");
      nodes[0].passReferences();
      System.out.println("*** Do the rest of initialization ***");
      for (int i = 0; i < nr_CPU; i++) {
         nodes[i].determineDistribution();
      }
      final Barrier barrier = BarrierFactory.createBarrier(nodes.length);
      final String filename = fname;
      Thread[] workers = new Thread[nr_CPU];
      for (int n = 0; n < workers.length; n++) {
         final SmackCluster node = nodes[n];
         workers[n] = new Thread(new Runnable(){
            
            public void run() {
               try {
                  node.solve(barrier);
               }  catch (Exception e) {
                  e.printStackTrace();
               }
            }
         });
      }
      System.out.println("*** Starting the solution ***");
      for (int n = 0; n < workers.length; n++) {
         workers[n].start();
      }
      long stime = System.currentTimeMillis();
      for (int n = 0; n < workers.length; n++) {
         try {
            workers[n].join();
         }  catch (InterruptedException e) {
            e.printStackTrace();
         }
      }
      System.out.println("Solving took " + (System.currentTimeMillis() - stime) + " ms");
   }
   public static void run_translator(String in_name, String out_name, int nr_CPU) throws RemoteException, Error {
      System.out.println("***********************************");
      System.out.println("*** Translator has been invoked ***");
      System.out.println("***********************************\n\n");
      Translator translatorinstance = new Translator();
      System.out.println("*** Reading & Translating***");
      translatorinstance.initialize(in_name, out_name);
      System.out.println("*** Initialization pass1 ***");
      translatorinstance.assembleMassMatrix();
      System.out.println("*** Initialization pass 2 ***");
      translatorinstance.setInitialConditions();
      System.out.println("*** Writing ***");
      translatorinstance.post();
   }
}
