#define EXTERNAL_FORCING /* why? wyao*/ #define MIN(x, y) (((x) < (y)) ? (x) : (y)) #define MAX(x, y) (((x) > (y)) ? (x) : (y)) #include #include #include #define READ_SWRAD #include "petscmat.h" #include "petsc_matvec_utils.h" #include "tmm_main.h" #include "tmm_forcing_utils.h" #include "tmm_profile_utils.h" #include "tmm_profile_data.h" #include "tmm_timer.h" #include "UVOK_TMM_OPTIONS.h" #include "uvok.h" #include "uvok_biogeochem_misfit_data.h" #define TR1 v[0] Vec Ts,Ss; PetscScalar *localTs,*localSs; PetscScalar **localTR, **localJTR; PetscBool useEmP = PETSC_TRUE; PetscScalar *localEmP, EmPglobavg; PeriodicArray localEmPp; Vec surfVolFrac; PetscScalar Sglobavg = 0.0, *TRglobavg; PetscScalar *localwind,*localaice,*localhice,*localhsno,*localdz,*localatmosp; PetscScalar *localswrad; PetscScalar *locallatitude; PetscScalar *localsgbathy; #ifdef O_npzd_fe_limitation Vec Fe_dissolved; PetscScalar *localFe_dissolved; PeriodicVec Fe_dissolvedp; #endif #ifdef O_npzd_iron PetscScalar *localFe_adep, *localFe_detr_flux; PeriodicArray localFe_adepp, localFe_detr_fluxp; Vec Fe_hydr; PetscScalar *localFe_hydr; #endif PetscScalar daysPerYear, secondsPerYear; #ifdef O_TMM_opt PetscInt nIter, nSession; #endif PetscInt nzmax; PetscScalar DeltaT; PetscScalar *drF, *zt; PeriodicVec Tsp, Ssp; PeriodicArray localwindp,localaicep,localhicep,localhsnop,localatmospp; #ifdef READ_SWRAD PeriodicArray localswradp; #endif PetscBool periodicBiogeochemForcing = PETSC_FALSE; PeriodicTimer biogeochemTimer; PetscInt maxValsToRead; /* variables for prescribed atmospheric CO2 */ #if defined O_carbon #if defined O_co2ccn_data char *pCO2atmFiles[2]; PetscInt numpCO2atm_hist = 0; PetscScalar *TpCO2atm_hist, *pCO2atm_hist; PetscScalar pCO2atm = 277.0; /* default initial value */ #endif #if defined O_TMM_interactive_atmosphere /* Land/Atm model variables */ PetscBool useLandModel = PETSC_FALSE; PetscBool useEmissions = PETSC_FALSE; PetscBool interpEmissions = PETSC_FALSE; char *emFiles[3]; PetscInt numEmission_hist = 0; PetscScalar *Tem_hist, *E_hist, *D_hist; PetscScalar fossilFuelEmission = 0.0, landUseEmission = 0.0; PetscScalar cumulativeEmissions = 0.0; PetscScalar pCO2atm_ini = 277.0; /* default initial value */ PetscScalar pCO2atm = 277.0; /* default initial value */ char pCO2atmIniFile[PETSC_MAX_PATH_LEN]; PetscScalar *localdA; PetscScalar landState[3], landSource[3]; PetscScalar deltaTsg = 0.0; PetscScalar ppmToPgC=2.1324; PetscScalar atmModelDeltaT; PetscScalar Fland = 0.0, Focean=0.0; PetscInt atmWriteSteps; PetscBool atmAppendOutput; FILE *atmfptime; PetscViewer atmfd; PetscInt atmfp; char atmOutTimeFile[PETSC_MAX_PATH_LEN]; PetscScalar pCO2atmavg, Foceanavg, Flandavg, landStateavg[3]; #endif # if defined O_c14ccn_data PetscScalar dc14ccnnatm = 0.0; PetscScalar dc14ccnsatm = 0.0; PetscScalar dc14ccneatm = 0.0; PetscScalar DC14atm = 0.0; /* default initial value */ char *C14atmFiles[2]; PetscScalar *TC14atm_hist, *C14atm_hist; PetscInt numC14atm_hist = 0; #endif #endif /* O_carbon */ PetscBool calcDiagnostics = PETSC_FALSE; StepTimer diagTimer; PetscBool diagFirstTime = PETSC_TRUE; PetscBool diagAppendOutput = PETSC_FALSE; PetscFileMode DIAG_FILE_MODE; FILE *diagfptime; PetscViewer diagfd; PetscInt diagfp; char diagOutTimeFile[PETSC_MAX_PATH_LEN]; /* Add model specific diagnostic variables below */ #define MAXDIAGS2d 40 #define MAXDIAGS3d 40 PetscScalar *localDiag2d[MAXDIAGS2d], *localDiag2davg[MAXDIAGS2d]; Vec *Diag3d, *Diag3davg; PetscScalar **localDiag3d, **localDiag3davg; PetscInt numDiags2d = 0, numDiags3d = 0, id2d, id3d; PetscViewer fddiag3dout[MAXDIAGS3d]; char *Diag2dFile[MAXDIAGS2d], *Diag3dFile[MAXDIAGS3d]; PetscInt doAverage=0; PetscMPIInt myId; PetscInt debugFlag = 0; PetscBool MYTRUE = PETSC_TRUE, MYFALSE = PETSC_FALSE; #if defined (FORSPINUP) || defined (FORJACOBIAN) PetscScalar relaxTau[50], relaxLambda[50], relaxValue[50]; PetscBool relaxTracer = PETSC_FALSE; #endif #undef __FUNCT__ #define __FUNCT__ "iniExternalForcing" PetscErrorCode iniExternalForcing(PetscScalar tc, PetscInt Iter, PetscInt numTracers, Vec *v, Vec *ut) { PetscErrorCode ierr; PetscInt ip, kl, nzloc; PetscInt itr; PetscViewer fd; PetscInt fp; PetscBool flg; PetscInt it, m; PetscScalar myTime; PetscScalar zero = 0.0; #if defined (FORSPINUP) || defined (FORJACOBIAN) ierr = PetscOptionsHasName(PETSC_NULL,"-relax_tracer",&relaxTracer);CHKERRQ(ierr); if (relaxTracer) { maxValsToRead = numTracers; ierr = PetscOptionsGetRealArray(PETSC_NULL,"-relax_tau",relaxTau,&maxValsToRead,&flg); if (!flg) SETERRQ(PETSC_COMM_WORLD,1,"Must indicate tracer relaxation tau with the -relax_tau option"); if (maxValsToRead != numTracers) { SETERRQ(PETSC_COMM_WORLD,1,"Insufficient number of relaxation tau values specified"); } maxValsToRead = numTracers; ierr = PetscOptionsGetRealArray(PETSC_NULL,"-relax_value",relaxValue,&maxValsToRead,&flg); if (!flg) SETERRQ(PETSC_COMM_WORLD,1,"Must indicate relaxation values with the -relax_value option"); if (maxValsToRead != numTracers) { SETERRQ(PETSC_COMM_WORLD,1,"Insufficient number of relaxation values specified"); } for (itr=0; itr0.0) { relaxLambda[itr]=1.0/relaxTau[itr]; } else { relaxLambda[itr]=0.0; relaxValue[itr]=0.0; } ierr = PetscPrintf(PETSC_COMM_WORLD,"Tracer %d relaxation lambda=%15.11f, relaxation value=%10.8f\n",itr,relaxLambda[itr],relaxValue[itr]);CHKERRQ(ierr); } } #endif /* This sequence should be identical to that in S/R tracer_init in UVic_ESCM.F */ m = 0; # if defined O_carbon #define dic v[m] #define sdic ut[m] m++; # if defined O_carbon_13 #define dic13 v[m] #define sdic13 ut[m] m++; # endif # if defined O_carbon_14 #define c14 v[m] #define sc14 ut[m] m++; # endif # endif # if defined O_npzd_alk #define alk v[m] #define salk ut[m] m++; # endif # if defined O_npzd_o2 #define o2 v[m] #define so2 ut[m] m++; # endif # if defined O_npzd #define po4 v[m] #define spo4 ut[m] m++; /*#define dop v[6] #define sdop ut[6] m++; */ #define phyt v[m] #define sphyt ut[m] m++; #define zoop v[m] #define szoop ut[m] m++; #define detr v[m] #define sdetr ut[m] m++; # if defined O_npzd_nitrogen #define no3 v[m] #define sno3 ut[m] m++; /*#define don v[11] #define sdon ut[11] m++; */ #define diaz v[m] #define sdiaz ut[m] m++; # if defined O_npzd_nitrogen_15 #define din15 v[m] #define sdin15 ut[m] m++; #define don15 v[m] #define sdon15 ut[m] m++; #define phytn15 v[m] #define sphytn15 ut[m] m++; #define zoopn15 v[m] #define szoopn15 ut[m] m++; #define detrn15 v[m] #define sdetrn15 ut[m] m++; #define diazn15 v[m] #define sdiazn15 ut[m] m++; # endif # endif # if defined O_carbon_13 #define doc13 v[m] #define sdoc13 ut[m] m++; #define phytc13 v[m] #define sphytc13 ut[m] m++; #define zoopc13 v[m] #define szoopc13 ut[m] m++; #define detrc13 v[m] #define sdetrc13 ut[m] m++; # if defined O_npzd_nitrogen #define diazc13 v[m] #define sdiazc13 ut[m] m++; # endif # endif # if defined O_npzd_iron #define dfe v[m] #define sdfe ut[m] m++; #define detrfe v[m] #define sdetrfe ut[m] m++; # endif # endif if (m != numTracers) { SETERRQ(PETSC_COMM_WORLD,1,"Error: numTracers does not match expected number of tracers!"); } for (itr=0; itr MAXDIAGS2d) { SETERRQ(PETSC_COMM_WORLD,1,"Number of 2-d diagnostics requested exceeds maximum. You must increase MAXDIAGS2d!"); } ierr = PetscPrintf(PETSC_COMM_WORLD,"Number of 2-d diagnostics requested: %d\n",numDiags2d);CHKERRQ(ierr); if (numDiags2d>0) { for (id2d=0; id2d MAXDIAGS3d) { SETERRQ(PETSC_COMM_WORLD,1,"Number of 3-d diagnostics requested exceeds maximum. You must increase MAXDIAGS3d!"); } ierr = PetscPrintf(PETSC_COMM_WORLD,"Number of 3-d diagnostics requested: %d\n",numDiags3d);CHKERRQ(ierr); if (numDiags2d == 0 & numDiags3d == 0) { SETERRQ(PETSC_COMM_WORLD,1,"You have specified the -calc_diagnostics flag but no diagnostics are being computed!"); } if (numDiags3d>0) { ierr = VecDuplicateVecs(TR1,numDiags3d,&Diag3davg);CHKERRQ(ierr); for (id3d=0; id3d=TpCO2atm_hist[0]) { ierr = calcInterpFactor(numpCO2atm_hist,tc,TpCO2atm_hist,&itf,&alpha); CHKERRQ(ierr); pCO2atm = alpha*pCO2atm_hist[itf] + (1.0-alpha)*pCO2atm_hist[itf+1]; } else { ierr = PetscPrintf(PETSC_COMM_WORLD,"Warning: time < %10.5f. Assuming pCO2atm=%g\n",TpCO2atm_hist[0],pCO2atm);CHKERRQ(ierr); } #endif #if defined O_TMM_interactive_atmosphere if (useEmissions) { /* Interpolate emissions */ if (tc>=Tem_hist[0]) { if (interpEmissions) { ierr = calcInterpFactor(numEmission_hist,tc,Tem_hist,&itf,&alpha); CHKERRQ(ierr); fossilFuelEmission = alpha*E_hist[itf] + (1.0-alpha)*E_hist[itf+1]; landUseEmission = alpha*D_hist[itf] + (1.0-alpha)*D_hist[itf+1]; } else { itf=findindex(Tem_hist,numEmission_hist,floor(tc)); fossilFuelEmission = E_hist[itf]; landUseEmission = D_hist[itf]; } } else { ierr = PetscPrintf(PETSC_COMM_WORLD,"Warning: time < %10.5f. Setting emissions to 0\n",Tem_hist[0]);CHKERRQ(ierr); fossilFuelEmission = 0.0; landUseEmission = 0.0; } cumulativeEmissions = cumulativeEmissions + atmModelDeltaT*(fossilFuelEmission + landUseEmission); /* PgC */ } #endif # if defined O_c14ccn_data if (tc>=TC14atm_hist[0]) { ierr = calcInterpFactor(numC14atm_hist,tc,TC14atm_hist,&itf,&alpha); CHKERRQ(ierr); DC14atm = alpha*C14atm_hist[itf] + (1.0-alpha)*C14atm_hist[itf+1]; dc14ccnnatm = DC14atm; dc14ccnsatm = DC14atm; dc14ccneatm = DC14atm; } else { ierr = PetscPrintf(PETSC_COMM_WORLD,"Warning: time < %10.5f. Assuming DC14atm=%g\n",TC14atm_hist[0],DC14atm);CHKERRQ(ierr); } #endif #endif /* O_carbon */ /* compute global means */ if (useEmP) { # if !defined O_constant_flux_reference for (itr=0; itr=costTimer.startTimeStep) { /* start time averaging (note: startTimeStep is ABSOLUTE time step) */ uvok_biogeochem_misfit_(&nzloc,&localmbgc1[kl],&localmbgc2[kl],&localmbgc3[kl] #ifdef O_TMM_opt_iron ,&localmbgc4[kl] #endif ); } } /* IK : added for misfit function : end */ /* IK : added for misfit function : end */ /* IK : added for misfit function : end */ #endif uvok_calc_(&nzloc,&locallatitude[ip],&day,&relyr, &localTs[kl],&localSs[kl],&TRglobavg[0],&localdz[kl],zt, # if defined O_carbon || defined O_npzd_o2 #if defined O_co2ccn_data || defined O_TMM_interactive_atmosphere &pCO2atm, #endif &localwind[ip], #endif # if defined O_c14ccn_data &dc14ccnnatm,&dc14ccnsatm,&dc14ccneatm, #endif # if defined O_npzd_subgridbathy &localsgbathy[kl], # endif # if defined O_npzd_fe_limitation &localFe_dissolved[kl], # endif #ifdef O_npzd_iron &localFe_adep[ip], &localFe_detr_flux[ip], &localFe_hydr[kl], #endif # if defined O_embm &localswrad[ip], # endif # if defined O_ice # if !defined O_ice_cpts &localaice[ip], &localhice[ip], &localhsno[ip], # endif # endif &localEmP[ip], &EmPglobavg, # if defined O_carbon &localgasexflux, &localtotflux, # endif &debugFlag); for (itr=0; itr=diagTimer.startTimeStep) { /* start time averaging (note: diagStartTimeStep is ABSOLUTE time step) */ uvok_diags_accumulate_(&ip, &kl, &nzloc, &diagTimer.count, &doAverage, &debugFlag); } } #if defined O_carbon #if defined O_TMM_interactive_atmosphere /* Note: following UVic (gasbc.F) we use the gas exchange flux to compute atmospheric CO2 evolution. */ /* The virtual flux term included in localtotflux should go be zero when integrated over the global ocean surface */ localFocean = localFocean + localgasexflux*localdA[ip]*(12.0/1.e15)*secondsPerYear; /* PgC/y */ #endif #endif /* O_carbon */ } /* end loop over profiles */ if (calcDiagnostics) { if (Iter0+iLoop>=diagTimer.startTimeStep) { /* start time averaging (note: diagStartTimeStep is ABSOLUTE time step) */ /* still within same averaging block so increment accumulate count */ diagTimer.count++; } } #if defined O_carbon #if defined O_TMM_interactive_atmosphere MPI_Allreduce(&localFocean, &Focean, 1, MPI_DOUBLE, MPI_SUM, PETSC_COMM_WORLD); if ((iLoop % atmWriteSteps)==0) { ierr = PetscPrintf(PETSC_COMM_WORLD,"Focean: %d = %10.5f\n", Iter, Focean);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD,"pCO2atm: %d = %10.5f\n", Iter, pCO2atm);CHKERRQ(ierr); } if (useLandModel) { /* landsource_(&landState[0],&pCO2atm,&landUseEmission,&deltaTsg,&Fland,&landSource[0]); */ /* returns S and Fl in PgC/y */ /* time step land */ for (k=0;k<=2;k++) { landState[k] = landState[k] + atmModelDeltaT*landSource[k]; } } /* time step atmosphere */ pCO2atm = pCO2atm + atmModelDeltaT*(fossilFuelEmission + landUseEmission - Focean - Fland)/ppmToPgC; #endif #endif /* O_carbon */ for (itr=0; itr=costTimer.startTimeStep) { /* start time averaging (note: startTimeStep is ABSOLUTE time step) */ ierr = VecSetValues(mbgc1,lSize,gIndices,localmbgc1,INSERT_VALUES);CHKERRQ(ierr); ierr = VecAssemblyBegin(mbgc1);CHKERRQ(ierr); ierr = VecAssemblyEnd(mbgc1);CHKERRQ(ierr); ierr = VecSetValues(mbgc2,lSize,gIndices,localmbgc2,INSERT_VALUES);CHKERRQ(ierr); ierr = VecAssemblyBegin(mbgc2);CHKERRQ(ierr); ierr = VecAssemblyEnd(mbgc2);CHKERRQ(ierr); ierr = VecSetValues(mbgc3,lSize,gIndices,localmbgc3,INSERT_VALUES);CHKERRQ(ierr); ierr = VecAssemblyBegin(mbgc3);CHKERRQ(ierr); ierr = VecAssemblyEnd(mbgc3);CHKERRQ(ierr); #ifdef O_TMM_opt_iron ierr = VecSetValues(mbgc4,lSize,gIndices,localmbgc4,INSERT_VALUES);CHKERRQ(ierr); ierr = VecAssemblyBegin(mbgc4);CHKERRQ(ierr); ierr = VecAssemblyEnd(mbgc4);CHKERRQ(ierr); #endif } } /* IK : added for misfit function : end */ /* IK : added for misfit function : end */ /* IK : added for misfit function : end */ #endif return 0; } #undef __FUNCT__ #define __FUNCT__ "writeExternalForcing" PetscErrorCode writeExternalForcing(PetscScalar tc, PetscInt iLoop, PetscInt numTracers, Vec *v, Vec *ut) { PetscErrorCode ierr; PetscInt ip, nzloc, kl; PetscScalar zero = 0.0, one = 1.0; /* Note: tc and iLoop are the time and step at the end of the current time step. */ #if defined O_carbon #if defined O_TMM_interactive_atmosphere /* write instantaneous atmos model state */ if ((iLoop % atmWriteSteps)==0) { /* time to write out */ ierr = PetscPrintf(PETSC_COMM_WORLD,"Writing atmospheric model output at time %10.5f, step %d\n", tc, Iter0+iLoop);CHKERRQ(ierr); ierr = PetscFPrintf(PETSC_COMM_WORLD,atmfptime,"%d %10.5f\n",Iter0+iLoop,tc);CHKERRQ(ierr); ierr = writeBinaryScalarData("pCO2atm_output.bin",&pCO2atm,1,PETSC_TRUE); if (useEmissions) { ierr = PetscPrintf(PETSC_COMM_WORLD,"Cumulative emissions at time %10.5f, step %d = %10.6f PgC\n", tc, Iter0+iLoop, cumulativeEmissions);CHKERRQ(ierr); } } if (useLandModel) { /* write instantaneous land model state */ if ((iLoop % atmWriteSteps)==0) { /* time to write out */ ierr = PetscPrintf(PETSC_COMM_WORLD,"Writing land model output at time %10.5f, step %d\n", tc, Iter0+iLoop);CHKERRQ(ierr); ierr = writeBinaryScalarData("land_state_output.bin",landState,3,PETSC_TRUE); } } #endif #endif /* O_carbon */ if (calcDiagnostics) { if (Iter0+iLoop>=diagTimer.startTimeStep) { /* start time averaging (note: diagStartTimeStep is ABSOLUTE time step) */ if (diagTimer.count==diagTimer.numTimeSteps) { /* time to write averages to file */ doAverage=1; for (ip=0; ip0) { for (id2d=0; id2d0) { for (id3d=0; id3d0) { ierr = VecDestroyVecs(numDiags3d,&Diag3davg);CHKERRQ(ierr); for (id3d=0; id3d