// 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; }
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); }
/* * 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 */ }
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(<); 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 */