Esempio n. 1
0
// OPENMPNOTE: Assume post_dt() not called by multiple threads, so static's are ok (including firsttime)
void postdt(void)
{
  static SFTYPE aftertime,beforetime;
  static int firsttime=1;
  static long beforenstep,afternstep;
  static FTYPE cour0;
  static int didfail;
  // check if failure.  If so, then grab restart from 2X ago (since
  // most previous restart may be too close to fixing problem), and
  // alter variables (cour) to fix.

  // assume failure doesn't occur in front of previous failure!


  if(firsttime){
    cour0=cour;
    //    cour0=0.9;

    // if no manual failure
    if(!restartonfail){
      didfail=0;
      beforenstep=0;
      beforetime=aftertime=0;
    }
    else{
      // use to start after failure and manual restart
      didfail=1;
      beforetime=911.944419026181;
      beforenstep=72425;
      aftertime=t;
      afternstep=realnstep;
    }
  }

  if((failed)&&(cour>1E-3)){
    beforenstep=realnstep;
    beforetime=t;
    // whichrestart is # of 2nd previous restart since next will use this #
    if (restart_init(whichrestart) >= 1) {
      dualfprintf(fail_file, "main:restart_init: failure\n");
    }
    afternstep=realnstep;
    aftertime=t;

    cour*=0.1;
    failed=0;
    didfail=1;
  }
  //  if((!failed)&&(realnstep>beforenstep+100)){
  if(didfail&&((!failed)&&(t>beforetime+1)) ){
    cour=cour0;
    aftertime=0;
    afternstep=0;
    beforetime=0;
    beforenstep=0;
    didfail=0;
    trifprintf("Made it through failiure!\n");
  }
  if(failed) myexit(0); // if still failed, then end.

  // other option is to alter variables right at failure, never
  // letting this postdt get activated, but that's done elsewhere.
  firsttime=0;
}
Esempio n. 2
0
int main(int argc, char *argv[])
{

  fprintf(stderr,"Start init\n"); fflush(stderr);

  /* perform initializations */
  pre_init(argc, argv);
  // all log files are now defined

  if (RESTARTMODE == 1) {
    if (restart_init(WHICHFILE) >= 1) {
      dualfprintf(fail_file, "main:restart_init: failure\n");
    }
  } else if (init() >= 1) {
    dualfprintf(fail_file, "main:init: failure\n");
  }

  post_init();			// initialize general parameters

  trifprintf("proc: %04d : End init\n", myid);


  /* Do initial diagnostics */
  if (DODIAGS) {
    trifprintf("proc: %04d : Start initial diagnostics\n", myid);
    // no error_check since if init passed, diag(0) should pass
    diag(0);
    trifprintf("proc: %04d : End initial diagnostics\n", myid);
  }

  trifprintf("proc: %04d : Start computation\n", myid);

  while (t < tf) {


    /* step variables forward in time */
    nstroke = 0;
    step_ch();

    // must check before MPI operation (since asymmetries would
    // desynchronize cpus)
    if (error_check()) {
      fprintf(fail_file, "error_check detected failure at main:2\n");
      fflush(fail_file);
    }
    //^^ otherwise ok
    
    // eventually all cpus come here, either in failure mode or not,
    // and cleanly tell others if failed/exit/dump/etc.

    postdt(); // here one can alter variables and try to restart, or implement any post step operations

    /* perform diagnostics */
    // no error check since assume if step_ch passed, diag(1) will pass
    if (DODIAGS)
      diag(1);

    /* restart dump */
    // if(nstep == 130) restart_write(1) ;

    nstep++;
    // restartsteps[whichrestart]=realnstep;


    trifprintf("%21.15g %21.15g %10.5g %8ld %8ld %8d\n", t, dt,
	      cour, nstep, realnstep, nstroke);
  }
  trifprintf("proc: %04d : End computation\n", myid);

  /* do final diagnostics */
  if (DODIAGS)
    diag(2);


  trifprintf("ns,ts: %ld %ld\n", nstep, nstep *(long)( totalsize[1] * totalsize[2]));

  myexit(0);
  return (0);
}
Esempio n. 3
0
/*
 * Return value:
 *   1 - exitlwps() failed, call (or continue) lwp_exit()
 *   0 - restarting init.  Return through system call path
 */
int
proc_exit(int why, int what)
{
	kthread_t *t = curthread;
	klwp_t *lwp = ttolwp(t);
	proc_t *p = ttoproc(t);
	zone_t *z = p->p_zone;
	timeout_id_t tmp_id;
	int rv;
	proc_t *q;
	task_t *tk;
	vnode_t *exec_vp, *execdir_vp, *cdir, *rdir;
	sigqueue_t *sqp;
	lwpdir_t *lwpdir;
	uint_t lwpdir_sz;
	tidhash_t *tidhash;
	uint_t tidhash_sz;
	ret_tidhash_t *ret_tidhash;
	refstr_t *cwd;
	hrtime_t hrutime, hrstime;
	int evaporate;

	/*
	 * Stop and discard the process's lwps except for the current one,
	 * unless some other lwp beat us to it.  If exitlwps() fails then
	 * return and the calling lwp will call (or continue in) lwp_exit().
	 */
	proc_is_exiting(p);
	if (exitlwps(0) != 0)
		return (1);

	mutex_enter(&p->p_lock);
	if (p->p_ttime > 0) {
		/*
		 * Account any remaining ticks charged to this process
		 * on its way out.
		 */
		(void) task_cpu_time_incr(p->p_task, p->p_ttime);
		p->p_ttime = 0;
	}
	mutex_exit(&p->p_lock);

	DTRACE_PROC(lwp__exit);
	DTRACE_PROC1(exit, int, why);

	/*
	 * Will perform any brand specific proc exit processing, since this
	 * is always the last lwp, will also perform lwp_exit and free brand
	 * data
	 */
	if (PROC_IS_BRANDED(p)) {
		lwp_detach_brand_hdlrs(lwp);
		brand_clearbrand(p, B_FALSE);
	}

	/*
	 * Don't let init exit unless zone_start_init() failed its exec, or
	 * we are shutting down the zone or the machine.
	 *
	 * Since we are single threaded, we don't need to lock the
	 * following accesses to zone_proc_initpid.
	 */
	if (p->p_pid == z->zone_proc_initpid) {
		if (z->zone_boot_err == 0 &&
		    zone_status_get(z) < ZONE_IS_SHUTTING_DOWN &&
		    zone_status_get(global_zone) < ZONE_IS_SHUTTING_DOWN &&
		    z->zone_restart_init == B_TRUE &&
		    restart_init(what, why) == 0)
			return (0);
		/*
		 * Since we didn't or couldn't restart init, we clear
		 * the zone's init state and proceed with exit
		 * processing.
		 */
		z->zone_proc_initpid = -1;
	}

	lwp_pcb_exit();

	/*
	 * Allocate a sigqueue now, before we grab locks.
	 * It will be given to sigcld(), below.
	 * Special case:  If we will be making the process disappear
	 * without a trace because it is either:
	 *	* an exiting SSYS process, or
	 *	* a posix_spawn() vfork child who requests it,
	 * we don't bother to allocate a useless sigqueue.
	 */
	evaporate = (p->p_flag & SSYS) || ((p->p_flag & SVFORK) &&
	    why == CLD_EXITED && what == _EVAPORATE);
	if (!evaporate)
		sqp = kmem_zalloc(sizeof (sigqueue_t), KM_SLEEP);

	/*
	 * revoke any doors created by the process.
	 */
	if (p->p_door_list)
		door_exit();

	/*
	 * Release schedctl data structures.
	 */
	if (p->p_pagep)
		schedctl_proc_cleanup();

	/*
	 * make sure all pending kaio has completed.
	 */
	if (p->p_aio)
		aio_cleanup_exit();

	/*
	 * discard the lwpchan cache.
	 */
	if (p->p_lcp != NULL)
		lwpchan_destroy_cache(0);

	/*
	 * Clean up any DTrace helper actions or probes for the process.
	 */
	if (p->p_dtrace_helpers != NULL) {
		ASSERT(dtrace_helpers_cleanup != NULL);
		(*dtrace_helpers_cleanup)();
	}

	/* untimeout the realtime timers */
	if (p->p_itimer != NULL)
		timer_exit();

	if ((tmp_id = p->p_alarmid) != 0) {
		p->p_alarmid = 0;
		(void) untimeout(tmp_id);
	}

	/*
	 * Remove any fpollinfo_t's for this (last) thread from our file
	 * descriptors so closeall() can ASSERT() that they're all gone.
	 */
	pollcleanup();

	if (p->p_rprof_cyclic != CYCLIC_NONE) {
		mutex_enter(&cpu_lock);
		cyclic_remove(p->p_rprof_cyclic);
		mutex_exit(&cpu_lock);
	}

	mutex_enter(&p->p_lock);

	/*
	 * Clean up any DTrace probes associated with this process.
	 */
	if (p->p_dtrace_probes) {
		ASSERT(dtrace_fasttrap_exit_ptr != NULL);
		dtrace_fasttrap_exit_ptr(p);
	}

	while ((tmp_id = p->p_itimerid) != 0) {
		p->p_itimerid = 0;
		mutex_exit(&p->p_lock);
		(void) untimeout(tmp_id);
		mutex_enter(&p->p_lock);
	}

	lwp_cleanup();

	/*
	 * We are about to exit; prevent our resource associations from
	 * being changed.
	 */
	pool_barrier_enter();

	/*
	 * Block the process against /proc now that we have really
	 * acquired p->p_lock (to manipulate p_tlist at least).
	 */
	prbarrier(p);

	sigfillset(&p->p_ignore);
	sigemptyset(&p->p_siginfo);
	sigemptyset(&p->p_sig);
	sigemptyset(&p->p_extsig);
	sigemptyset(&t->t_sig);
	sigemptyset(&t->t_extsig);
	sigemptyset(&p->p_sigmask);
	sigdelq(p, t, 0);
	lwp->lwp_cursig = 0;
	lwp->lwp_extsig = 0;
	p->p_flag &= ~(SKILLED | SEXTKILLED);
	if (lwp->lwp_curinfo) {
		siginfofree(lwp->lwp_curinfo);
		lwp->lwp_curinfo = NULL;
	}

	t->t_proc_flag |= TP_LWPEXIT;
	ASSERT(p->p_lwpcnt == 1 && p->p_zombcnt == 0);
	prlwpexit(t);		/* notify /proc */
	lwp_hash_out(p, t->t_tid);
	prexit(p);

	p->p_lwpcnt = 0;
	p->p_tlist = NULL;
	sigqfree(p);
	term_mstate(t);
	p->p_mterm = gethrtime();

	exec_vp = p->p_exec;
	execdir_vp = p->p_execdir;
	p->p_exec = NULLVP;
	p->p_execdir = NULLVP;
	mutex_exit(&p->p_lock);

	pr_free_watched_pages(p);

	closeall(P_FINFO(p));

	/* Free the controlling tty.  (freectty() always assumes curproc.) */
	ASSERT(p == curproc);
	(void) freectty(B_TRUE);

#if defined(__sparc)
	if (p->p_utraps != NULL)
		utrap_free(p);
#endif
	if (p->p_semacct)			/* IPC semaphore exit */
		semexit(p);
	rv = wstat(why, what);

	acct(rv & 0xff);
	exacct_commit_proc(p, rv);

	/*
	 * Release any resources associated with C2 auditing
	 */
	if (AU_AUDITING()) {
		/*
		 * audit exit system call
		 */
		audit_exit(why, what);
	}

	/*
	 * Free address space.
	 */
	relvm();

	if (exec_vp) {
		/*
		 * Close this executable which has been opened when the process
		 * was created by getproc().
		 */
		(void) VOP_CLOSE(exec_vp, FREAD, 1, (offset_t)0, CRED(), NULL);
		VN_RELE(exec_vp);
	}
	if (execdir_vp)
		VN_RELE(execdir_vp);

	/*
	 * Release held contracts.
	 */
	contract_exit(p);

	/*
	 * Depart our encapsulating process contract.
	 */
	if ((p->p_flag & SSYS) == 0) {
		ASSERT(p->p_ct_process);
		contract_process_exit(p->p_ct_process, p, rv);
	}

	/*
	 * Remove pool association, and block if requested by pool_do_bind.
	 */
	mutex_enter(&p->p_lock);
	ASSERT(p->p_pool->pool_ref > 0);
	atomic_add_32(&p->p_pool->pool_ref, -1);
	p->p_pool = pool_default;
	/*
	 * Now that our address space has been freed and all other threads
	 * in this process have exited, set the PEXITED pool flag.  This
	 * tells the pools subsystems to ignore this process if it was
	 * requested to rebind this process to a new pool.
	 */
	p->p_poolflag |= PEXITED;
	pool_barrier_exit();
	mutex_exit(&p->p_lock);

	mutex_enter(&pidlock);

	/*
	 * Delete this process from the newstate list of its parent. We
	 * will put it in the right place in the sigcld in the end.
	 */
	delete_ns(p->p_parent, p);

	/*
	 * Reassign the orphans to the next of kin.
	 * Don't rearrange init's orphanage.
	 */
	if ((q = p->p_orphan) != NULL && p != proc_init) {

		proc_t *nokp = p->p_nextofkin;

		for (;;) {
			q->p_nextofkin = nokp;
			if (q->p_nextorph == NULL)
				break;
			q = q->p_nextorph;
		}
		q->p_nextorph = nokp->p_orphan;
		nokp->p_orphan = p->p_orphan;
		p->p_orphan = NULL;
	}

	/*
	 * Reassign the children to init.
	 * Don't try to assign init's children to init.
	 */
	if ((q = p->p_child) != NULL && p != proc_init) {
		struct proc	*np;
		struct proc	*initp = proc_init;
		boolean_t	setzonetop = B_FALSE;

		if (!INGLOBALZONE(curproc))
			setzonetop = B_TRUE;

		pgdetach(p);

		do {
			np = q->p_sibling;
			/*
			 * Delete it from its current parent new state
			 * list and add it to init new state list
			 */
			delete_ns(q->p_parent, q);

			q->p_ppid = 1;
			q->p_pidflag &= ~(CLDNOSIGCHLD | CLDWAITPID);
			if (setzonetop) {
				mutex_enter(&q->p_lock);
				q->p_flag |= SZONETOP;
				mutex_exit(&q->p_lock);
			}
			q->p_parent = initp;

			/*
			 * Since q will be the first child,
			 * it will not have a previous sibling.
			 */
			q->p_psibling = NULL;
			if (initp->p_child) {
				initp->p_child->p_psibling = q;
			}
			q->p_sibling = initp->p_child;
			initp->p_child = q;
			if (q->p_proc_flag & P_PR_PTRACE) {
				mutex_enter(&q->p_lock);
				sigtoproc(q, NULL, SIGKILL);
				mutex_exit(&q->p_lock);
			}
			/*
			 * sigcld() will add the child to parents
			 * newstate list.
			 */
			if (q->p_stat == SZOMB)
				sigcld(q, NULL);
		} while ((q = np) != NULL);

		p->p_child = NULL;
		ASSERT(p->p_child_ns == NULL);
	}

	TRACE_1(TR_FAC_PROC, TR_PROC_EXIT, "proc_exit: %p", p);

	mutex_enter(&p->p_lock);
	CL_EXIT(curthread); /* tell the scheduler that curthread is exiting */

	/*
	 * Have our task accummulate our resource usage data before they
	 * become contaminated by p_cacct etc., and before we renounce
	 * membership of the task.
	 *
	 * We do this regardless of whether or not task accounting is active.
	 * This is to avoid having nonsense data reported for this task if
	 * task accounting is subsequently enabled. The overhead is minimal;
	 * by this point, this process has accounted for the usage of all its
	 * LWPs. We nonetheless do the work here, and under the protection of
	 * pidlock, so that the movement of the process's usage to the task
	 * happens at the same time as the removal of the process from the
	 * task, from the point of view of exacct_snapshot_task_usage().
	 */
	exacct_update_task_mstate(p);

	hrutime = mstate_aggr_state(p, LMS_USER);
	hrstime = mstate_aggr_state(p, LMS_SYSTEM);
	p->p_utime = (clock_t)NSEC_TO_TICK(hrutime) + p->p_cutime;
	p->p_stime = (clock_t)NSEC_TO_TICK(hrstime) + p->p_cstime;

	p->p_acct[LMS_USER]	+= p->p_cacct[LMS_USER];
	p->p_acct[LMS_SYSTEM]	+= p->p_cacct[LMS_SYSTEM];
	p->p_acct[LMS_TRAP]	+= p->p_cacct[LMS_TRAP];
	p->p_acct[LMS_TFAULT]	+= p->p_cacct[LMS_TFAULT];
	p->p_acct[LMS_DFAULT]	+= p->p_cacct[LMS_DFAULT];
	p->p_acct[LMS_KFAULT]	+= p->p_cacct[LMS_KFAULT];
	p->p_acct[LMS_USER_LOCK] += p->p_cacct[LMS_USER_LOCK];
	p->p_acct[LMS_SLEEP]	+= p->p_cacct[LMS_SLEEP];
	p->p_acct[LMS_WAIT_CPU]	+= p->p_cacct[LMS_WAIT_CPU];
	p->p_acct[LMS_STOPPED]	+= p->p_cacct[LMS_STOPPED];

	p->p_ru.minflt	+= p->p_cru.minflt;
	p->p_ru.majflt	+= p->p_cru.majflt;
	p->p_ru.nswap	+= p->p_cru.nswap;
	p->p_ru.inblock	+= p->p_cru.inblock;
	p->p_ru.oublock	+= p->p_cru.oublock;
	p->p_ru.msgsnd	+= p->p_cru.msgsnd;
	p->p_ru.msgrcv	+= p->p_cru.msgrcv;
	p->p_ru.nsignals += p->p_cru.nsignals;
	p->p_ru.nvcsw	+= p->p_cru.nvcsw;
	p->p_ru.nivcsw	+= p->p_cru.nivcsw;
	p->p_ru.sysc	+= p->p_cru.sysc;
	p->p_ru.ioch	+= p->p_cru.ioch;

	p->p_stat = SZOMB;
	p->p_proc_flag &= ~P_PR_PTRACE;
	p->p_wdata = what;
	p->p_wcode = (char)why;

	cdir = PTOU(p)->u_cdir;
	rdir = PTOU(p)->u_rdir;
	cwd = PTOU(p)->u_cwd;

	ASSERT(cdir != NULL || p->p_parent == &p0);

	/*
	 * Release resource controls, as they are no longer enforceable.
	 */
	rctl_set_free(p->p_rctls);

	/*
	 * Decrement tk_nlwps counter for our task.max-lwps resource control.
	 * An extended accounting record, if that facility is active, is
	 * scheduled to be written.  We cannot give up task and project
	 * membership at this point because that would allow zombies to escape
	 * from the max-processes resource controls.  Zombies stay in their
	 * current task and project until the process table slot is released
	 * in freeproc().
	 */
	tk = p->p_task;

	mutex_enter(&p->p_zone->zone_nlwps_lock);
	tk->tk_nlwps--;
	tk->tk_proj->kpj_nlwps--;
	p->p_zone->zone_nlwps--;
	mutex_exit(&p->p_zone->zone_nlwps_lock);

	/*
	 * Clear the lwp directory and the lwpid hash table
	 * now that /proc can't bother us any more.
	 * We free the memory below, after dropping p->p_lock.
	 */
	lwpdir = p->p_lwpdir;
	lwpdir_sz = p->p_lwpdir_sz;
	tidhash = p->p_tidhash;
	tidhash_sz = p->p_tidhash_sz;
	ret_tidhash = p->p_ret_tidhash;
	p->p_lwpdir = NULL;
	p->p_lwpfree = NULL;
	p->p_lwpdir_sz = 0;
	p->p_tidhash = NULL;
	p->p_tidhash_sz = 0;
	p->p_ret_tidhash = NULL;

	/*
	 * If the process has context ops installed, call the exit routine
	 * on behalf of this last remaining thread. Normally exitpctx() is
	 * called during thread_exit() or lwp_exit(), but because this is the
	 * last thread in the process, we must call it here. By the time
	 * thread_exit() is called (below), the association with the relevant
	 * process has been lost.
	 *
	 * We also free the context here.
	 */
	if (p->p_pctx) {
		kpreempt_disable();
		exitpctx(p);
		kpreempt_enable();

		freepctx(p, 0);
	}

	/*
	 * curthread's proc pointer is changed to point to the 'sched'
	 * process for the corresponding zone, except in the case when
	 * the exiting process is in fact a zsched instance, in which
	 * case the proc pointer is set to p0.  We do so, so that the
	 * process still points at the right zone when we call the VN_RELE()
	 * below.
	 *
	 * This is because curthread's original proc pointer can be freed as
	 * soon as the child sends a SIGCLD to its parent.  We use zsched so
	 * that for user processes, even in the final moments of death, the
	 * process is still associated with its zone.
	 */
	if (p != t->t_procp->p_zone->zone_zsched)
		t->t_procp = t->t_procp->p_zone->zone_zsched;
	else
		t->t_procp = &p0;

	mutex_exit(&p->p_lock);
	if (!evaporate) {
		p->p_pidflag &= ~CLDPEND;
		sigcld(p, sqp);
	} else {
		/*
		 * Do what sigcld() would do if the disposition
		 * of the SIGCHLD signal were set to be ignored.
		 */
		cv_broadcast(&p->p_srwchan_cv);
		freeproc(p);
	}
	mutex_exit(&pidlock);

	/*
	 * We don't release u_cdir and u_rdir until SZOMB is set.
	 * This protects us against dofusers().
	 */
	if (cdir)
		VN_RELE(cdir);
	if (rdir)
		VN_RELE(rdir);
	if (cwd)
		refstr_rele(cwd);

	/*
	 * task_rele() may ultimately cause the zone to go away (or
	 * may cause the last user process in a zone to go away, which
	 * signals zsched to go away).  So prior to this call, we must
	 * no longer point at zsched.
	 */
	t->t_procp = &p0;

	kmem_free(lwpdir, lwpdir_sz * sizeof (lwpdir_t));
	kmem_free(tidhash, tidhash_sz * sizeof (tidhash_t));
	while (ret_tidhash != NULL) {
		ret_tidhash_t *next = ret_tidhash->rth_next;
		kmem_free(ret_tidhash->rth_tidhash,
		    ret_tidhash->rth_tidhash_sz * sizeof (tidhash_t));
		kmem_free(ret_tidhash, sizeof (*ret_tidhash));
		ret_tidhash = next;
	}

	thread_exit();
	/* NOTREACHED */
}
Esempio n. 4
0
int main(int argc, char *argv[])
{
	/* bgc input and output structures */
	bgcin_struct bgcin;
	bgcout_struct bgcout;

	/* local control information */
	point_struct point;
	restart_ctrl_struct restart;
	climchange_struct scc;
	output_struct output;
	
	/* initialization file */
	file init;
	file ndep_file;

	/* system time variables */
	struct tm *tm_ptr;
	time_t lt;

	extern signed char summary_sanity;

	int c; /* for getopt cli argument processing */
	extern signed char bgc_verbosity;
	extern int optind, opterr;
	unsigned char bgc_ascii = 0;
	extern char *optarg;
	extern signed char cli_mode; /* What cli requested mode to run in.*/
	int readndepfile = 0;		/* Flag to tell the program to read an external NDEP file passed using getpopt -n */
	
	bgcin.ndepctrl.varndep = 0;
	/* Store command name for use by bgc_print_usage() */
	argv_zero = (char *)malloc(strlen(argv[0])+1);
	strncpy(argv_zero, argv[0], strlen(argv[0])+1);

	/* Process command line arguments */
	opterr = 0;
	while((c = getopt(argc, argv, "pVsl:v:ugmn:a")) != -1)
	{
		switch(c)
		{
			case 'V':
				bgc_printf(BV_ERROR, "BiomeBGC version %s (built %s %s by %s on %s)\n", VERS, __DATE__, __TIME__, USER, HOST);
				exit(EXIT_SUCCESS);
				break;
			case 's':
				bgc_verbosity = BV_SILENT;
				break;
			case 'v':
				bgc_verbosity = bgc_verbosity_decode(optarg);
				break;
			case 'l':
				bgc_logfile_setup(optarg);
				bgc_printf(BV_DIAG, "Using logfile for output.\n");
				break;
			case 'p':
				summary_sanity = SANE;
				break;
			case 'u':
				cli_mode = MODE_SPINUP;
				break;
			case 'm':
				cli_mode = MODE_MODEL;
				break;
			case 'g':
				cli_mode = MODE_SPINNGO;
				break;
			case 'a':
				bgc_ascii = 1;
				break;
			case 'n':  /* Nitrogen deposition file */
				strcpy(ndep_file.name,optarg);
				bgc_printf(BV_DIAG,"Using annual NDEP file: %s\n",ndep_file.name);
				readndepfile = 1;
				bgcin.ndepctrl.varndep = 1;
				break;
				
			case '?':
				break;
			default:
				break;
			}
	}

	bgc_printf(BV_DIAG, "Verbosity Level Set To: %d\n", bgc_verbosity);
	
	if (summary_sanity == SANE)
		bgc_printf(BV_WARN, "Summary outputs will be calculated more sanely. See USAGE.TXT for details\n");

	if (cli_mode != MODE_INI)
	{
		bgc_printf(BV_WARN, "Overridding ini mode. ");
		if (cli_mode == MODE_SPINUP)
			bgc_printf(BV_WARN, "Running in Spinup Mode.\n");
		if (cli_mode == MODE_MODEL)
			bgc_printf(BV_WARN, "Running in Model mode.\n");
		if (cli_mode == MODE_SPINNGO)
			bgc_printf(BV_WARN, "Running in Spin-and-Go mode.\nThe spinup and model will both be run.\n");
	}
		
	bgc_printf(BV_DIAG, "Done processing CLI arguments.\n");

	/* get the system time at start of simulation */
	lt = time(NULL);
	tm_ptr = localtime(&lt);
	strcpy(point.systime,asctime(tm_ptr));
	/* Andrew tried this, you shouldn't. localtime returns a global extern. */
	/* free(tm_ptr); */
	output.anncodes = NULL;
	output.daycodes = NULL;
	output.bgc_ascii = bgc_ascii;
	
	/* initialize the bgcin state variable structures before filling with
	values from ini file */
	if (presim_state_init(&bgcin.ws, &bgcin.cs, &bgcin.ns, &bgcin.cinit))
	{
		bgc_printf(BV_ERROR, "Error in call to presim_state_init() from pointbgc()\n");
		exit(EXIT_FAILURE);
	}

	/******************************
	**                           **
	**  BEGIN READING INIT FILE  **
	**                           **
	******************************/

	/* read the name of the main init file from the command line
	and store as init.name */
	if (optind >= argc )
	{
		bgc_print_usage();
		exit(EXIT_FAILURE);
	}
	strcpy(init.name, argv[optind]);
	
	/* open the main init file for ascii read and check for errors */
	if (file_open(&init,'i'))
	{
		bgc_printf(BV_ERROR, "Error opening init file, pointbgc.c\n");
		exit(EXIT_FAILURE);
	}

	/* read the header string from the init file */
	if (fgets(point.header, 100, init.ptr)==NULL)
	{
		bgc_printf(BV_ERROR, "Error reading header string: pointbgc.c\n");
		exit(EXIT_FAILURE);
	}

	/* open met file, discard header lines */
	if (met_init(init, &point))
	{
		bgc_printf(BV_ERROR, "Error in call to met_init() from pointbgc.c... Exiting\n");
		exit(EXIT_FAILURE);
	}

	/* read restart control parameters */
	if (restart_init(init, &restart))
	{
		bgc_printf(BV_ERROR, "Error in call to restart_init() from pointbgc.c... Exiting\n");
		exit(EXIT_FAILURE);
	}

	/* read simulation timing control parameters */
	if (time_init(init, &(bgcin.ctrl)))
	{
		bgc_printf(BV_ERROR, "Error in call to epclist_init() from pointbgc.c... Exiting\n");
		exit(EXIT_FAILURE);
	}
	
	/* read scalar climate change parameters */
	if (scc_init(init, &scc))
	{
		bgc_printf(BV_ERROR, "Error in call to scc_init() from pointbgc.c... Exiting\n");
		exit(EXIT_FAILURE);
	}
	
	/* read CO2 control parameters */
	if (co2_init(init, &(bgcin.co2), bgcin.ctrl.simyears))
	{
		bgc_printf(BV_ERROR, "Error in call to co2_init() from pointbgc.c... Exiting\n");
		exit(EXIT_FAILURE);
	}
	if(readndepfile)
	{
		if (ndep_init(ndep_file, &(bgcin.ndepctrl)))
		{
			bgc_printf(BV_ERROR, "Error in call to ndep_init() from pointbgc.c... Exiting\n");
			exit(EXIT_FAILURE);
		}
	}
	/* read site constants */
	if (sitec_init(init, &bgcin.sitec))
	{
		bgc_printf(BV_ERROR, "Error in call to sitec_init() from pointbgc.c... Exiting\n");
		exit(EXIT_FAILURE);
	}
	
	/* read ramped nitrogen deposition block */
	if (ramp_ndep_init(init, &bgcin.ramp_ndep))
	{
		bgc_printf(BV_ERROR, "Error in call to ramp_ndep_init() from pointbgc.c... Exiting\n");
		exit(EXIT_FAILURE);
	}
	
	/* read ecophysiological constants */
	if (epc_init(init, &bgcin.epc))
	{
		bgc_printf(BV_ERROR, "Error in call to epc_init() from pointbgc.c... Exiting\n");
		exit(EXIT_FAILURE);
	}

	/* initialize water state structure */
	if (wstate_init(init, &bgcin.sitec, &bgcin.ws))
	{
		bgc_printf(BV_ERROR, "Error in call to wstate_init() from pointbgc.c... Exiting\n");
		exit(EXIT_FAILURE);
	}

	/* initialize carbon and nitrogen state structures */
	if (cnstate_init(init, &bgcin.epc, &bgcin.cs, &bgcin.cinit,
		&bgcin.ns))
	{
		bgc_printf(BV_ERROR, "Error in call to cstate_init() from pointbgc.c... Exiting\n");
		exit(EXIT_FAILURE);
	}

	/* read the output control information */
	if (output_ctrl(init, &output))
	{
		bgc_printf(BV_ERROR, "Error in call to output_ctrl() from pointbgc.c... Exiting\n");
		exit(EXIT_FAILURE);
	}
	
	/* initialize output files. Does nothing in spinup mode*/
	if (output_init(&output))
	{
		bgc_printf(BV_ERROR, "Error in call to output_init() from pointbgc.c... Exiting\n");
		exit(EXIT_FAILURE);
	}
	
	/* read final line out of init file to test for proper file structure */
	if (end_init(init))
	{
		bgc_printf(BV_ERROR, "Error in call to end_init() from pointbgc.c... exiting\n");
		exit(EXIT_FAILURE);
	}
	fclose(init.ptr);

	/* read meteorology file, build metarr arrays, compute running avgs */
	if (metarr_init(point.metf, &bgcin.metarr, &scc, bgcin.ctrl.metyears))
	{
		bgc_printf(BV_ERROR, "Error in call to metarr_init() from pointbgc.c... Exiting\n");
		exit(EXIT_FAILURE);
	}
	fclose(point.metf.ptr);

	/* copy some of the info from input structure to bgc simulation control
	structure */
	bgcin.ctrl.onscreen = output.onscreen;
	bgcin.ctrl.dodaily = output.dodaily;
	bgcin.ctrl.domonavg = output.domonavg;
	bgcin.ctrl.doannavg = output.doannavg;
	bgcin.ctrl.doannual = output.doannual;
	bgcin.ctrl.ndayout = output.ndayout;
	bgcin.ctrl.nannout = output.nannout;
	bgcin.ctrl.daycodes = output.daycodes;
	bgcin.ctrl.anncodes = output.anncodes;
	bgcin.ctrl.read_restart = restart.read_restart;
	bgcin.ctrl.write_restart = restart.write_restart;
	bgcin.ctrl.keep_metyr = restart.keep_metyr;
	
	/* copy the output file structures into bgcout */
	if (output.dodaily) bgcout.dayout = output.dayout;
	if (output.domonavg) bgcout.monavgout = output.monavgout;
	if (output.doannavg) bgcout.annavgout = output.annavgout;
	if (output.doannual) bgcout.annout = output.annout;
	if (output.bgc_ascii && output.dodaily) bgcout.dayoutascii = output.dayoutascii;
	if (output.bgc_ascii && output.domonavg) bgcout.monoutascii = output.monoutascii;
	if (output.bgc_ascii && output.doannual) bgcout.annoutascii = output.annoutascii;
	bgcout.anntext = output.anntext;
	bgcout.bgc_ascii = bgc_ascii;
	
	/* if using ramped Ndep, copy preindustrial Ndep into ramp_ndep struct */
	if (bgcin.ramp_ndep.doramp)
	{
		bgcin.ramp_ndep.preind_ndep = bgcin.sitec.ndep;
	}
	
	/* if using an input restart file, read a record */
	if (restart.read_restart)
	{
		/* 02/06/04
		 * The if statement gaurds against core dump on bad restart file.
		 * If spinup exits with error then the norm trys to use the restart,
		 * that has nothing in it, a seg fault occurs. Amac */
		if( fread(&(bgcin.restart_input),sizeof(restart_data_struct),1,restart.in_restart.ptr) == 0)
		{
			bgc_printf(BV_ERROR, "Error reading restart file! 0 bytes read. Aborting..\n");
			exit(EXIT_FAILURE);
		}
	}

	/*********************
	**                  **
	**  CALL BIOME-BGC  **
	**                  **
	*********************/

	/* all initialization complete, call model */
	/* either call the spinup code or the normal simulation code */
	if (bgcin.ctrl.spinup)
	{
		if (bgc(&bgcin, &bgcout,MODE_SPINUP))
		{
			bgc_printf(BV_ERROR, "Error in call to bgc()\n");
			exit(EXIT_FAILURE);
		}
		bgc_printf(BV_PROGRESS, "SPINUP: residual trend  = %.6lf\n",bgcout.spinup_resid_trend);
		bgc_printf(BV_PROGRESS, "SPINUP: number of years = %d\n",bgcout.spinup_years);
	}
	else
	{
		if (bgc(&bgcin, &bgcout, MODE_MODEL))
		{
			bgc_printf(BV_ERROR, "Error in call to bgc()\n");
			exit(EXIT_FAILURE);
		}
	}
		

	/* if using an output restart file, write a record */
	if (restart.write_restart)
	{
		fwrite(&(bgcout.restart_output),sizeof(restart_data_struct),1,
			restart.out_restart.ptr);
	}
	
	/* Now do the Model part of Spin & Go. */
	if (cli_mode == MODE_SPINNGO)
	{
		bgc_printf(BV_PROGRESS, "Finished Spinup for Spin 'n Go. Now starting Model run ('Go' part of Spin'n Go)\n");
			
		bgc_printf(BV_PROGRESS, "Assigned bgcout struct to bgcin for spinngo model run\n");
		
		bgcin.ctrl.spinup = 0;
		output.doannavg = 1;
		output.doannual = 1;
		output.dodaily = 1;
		output.domonavg = 1;
		
		if (output_init(&output))
		{
			bgc_printf(BV_ERROR, "Error in call to output_init() from pointbgc.c... Exiting\n");
			exit(EXIT_FAILURE);
		}
		
		/* copy some of the info from input structure to bgc simulation control structure */
		bgcin.ctrl.dodaily = output.dodaily;
		bgcin.ctrl.domonavg = output.domonavg;
		bgcin.ctrl.doannavg = output.doannavg;
		bgcin.ctrl.doannual = output.doannual;
	
		/* copy the output file structures into bgcout */
		if (output.dodaily) bgcout.dayout = output.dayout;
		if (output.domonavg) bgcout.monavgout = output.monavgout;
		if (output.doannavg) bgcout.annavgout = output.annavgout;
		if (output.doannual) bgcout.annout = output.annout;
		if (output.bgc_ascii && output.dodaily) bgcout.dayoutascii = output.dayoutascii;
		if (output.bgc_ascii && output.domonavg) bgcout.monoutascii = output.monoutascii;
		if (output.bgc_ascii && output.doannual) bgcout.annoutascii = output.annoutascii;
		if (output.bgc_ascii && output.doannual) bgcout.anntext = output.anntext;
		
		/* initialize output files. Does nothing in spinup mode*/
		
		
		bgcin.ctrl.read_restart = 1;
		bgcin.restart_input = bgcout.restart_output;
		
		if (bgc(&bgcin, &bgcout, MODE_MODEL))
		{
			bgc_printf(BV_ERROR, "Error in call to bgc()\n");
			exit(EXIT_FAILURE);
		}
		restart.read_restart = 0;
		bgcin.ctrl.read_restart = 0;

		bgc_printf(BV_WARN, "Finished the bgc() Model call in spinngo\n");
		
	}

	/* post-processing output handling, if any, goes here */
	
	/* free memory */
	free(bgcin.metarr.tmax);
	free(bgcin.metarr.tmin);
	free(bgcin.metarr.prcp);
	free(bgcin.metarr.vpd);
	free(bgcin.metarr.tavg);
	free(bgcin.metarr.tavg_ra);
	free(bgcin.metarr.swavgfd);
	free(bgcin.metarr.par);
	free(bgcin.metarr.dayl);
	if (bgcin.co2.varco2) free(bgcin.co2.co2ppm_array);
	if (bgcin.ndepctrl.varndep) free(bgcin.ndepctrl.ndepyear_array);
	if (bgcin.ndepctrl.varndep) free(bgcin.ndepctrl.ndep_array);
	if (output.anncodes != NULL) free(output.anncodes);
	if (output.daycodes != NULL) free(output.daycodes);
	
	/* close files */
	if (restart.read_restart) fclose(restart.in_restart.ptr);
	if (restart.write_restart) {
		if (fclose(restart.out_restart.ptr) != 0)
		{
			bgc_printf(BV_WARN, "Warning, error closing restart file after write: %s\n", strerror(errno));
		}
	}
	if (output.dodaily) fclose(output.dayout.ptr);
	if (output.domonavg) fclose(output.monavgout.ptr);
	if (output.doannavg) fclose(output.annavgout.ptr);
	if (output.doannual) fclose(output.annout.ptr);
	/* Close the ASCII output files */
	if (output.bgc_ascii && output.dodaily) fclose(output.dayoutascii.ptr);
	if (output.bgc_ascii && output.domonavg) fclose(output.monoutascii.ptr);
	if (output.bgc_ascii && output.doannual) fclose(output.annoutascii.ptr);
	
	if ( output.bgc_ascii && output.doannual && (fclose(output.anntext.ptr) != 0))
	{
		bgc_printf(BV_WARN, "Warning, error closing ascii annual output file: %s\n", strerror(errno));
	}

	bgc_logfile_finish();
	free(argv_zero);
	return EXIT_SUCCESS;
} /* end of main */