/*!\file StochasticForcingx * \brief: compute noise terms for the StochasticForcing fields */ #include "./StochasticForcingx.h" #include "../../classes/Loads/Friction.h" #include "../../shared/shared.h" #include "../../toolkits/toolkits.h" #include "../../shared/Random/random.h" void StochasticForcingx(FemModel* femmodel){/*{{{*/ /*Retrieve parameters*/ bool randomflag; int M,N,numfields,numtcov,my_rank; int* fields = NULL; int* dimensions = NULL; IssmDouble* timecovariance = NULL; IssmDouble* covariance = NULL; femmodel->parameters->FindParam(&randomflag,StochasticForcingRandomflagEnum); femmodel->parameters->FindParam(&numfields,StochasticForcingNumFieldsEnum); femmodel->parameters->FindParam(&numtcov,StochasticForcingNumTimesCovarianceEnum); femmodel->parameters->FindParam(&fields,&N,StochasticForcingFieldsEnum); _assert_(N==numfields); femmodel->parameters->FindParam(&dimensions,&N,StochasticForcingDimensionsEnum); _assert_(N==numfields); femmodel->parameters->FindParam(&timecovariance,&N,StochasticForcingTimeCovarianceEnum); _assert_(N==numtcov); int dimtot=0; for(int i=0;iparameters->FindParam(&covariance,&M,&N,StochasticForcingCovarianceEnum); _assert_(M==numtcov); _assert_(N==dimtot*dimtot); /*Check if this is a timestep for new noiseterms computation*/ bool isstepforstoch = false; IssmDouble time,dt,starttime,tstep_stoch; femmodel->parameters->FindParam(&time,TimeEnum); femmodel->parameters->FindParam(&dt,TimesteppingTimeStepEnum); femmodel->parameters->FindParam(&starttime,TimesteppingStartTimeEnum); femmodel->parameters->FindParam(&tstep_stoch,StochasticForcingTimestepEnum); /*Check if we use HydroarmaPw*/ bool ispwHydro; femmodel->parameters->FindParam(&ispwHydro,HydrologyIsWaterPressureArmaEnum); #ifndef _HAVE_AD_ if((fmod(time,tstep_stoch)(dimtot*dimtot); IssmDouble* noiseterms = xNew(dimtot); if(isstepforstoch){ /*Find covariance to be applied at current time step*/ int itime; if(numtcov>1){ for(int i=0;i=timecovariance[i]) itime=i; } } else itime=0; for(int i=0;i((time-starttime)/dt); /*multivariateNormal needs to be passed a NULL pointer to avoid memory leak issues*/ IssmDouble* temparray = NULL; multivariateNormal(&temparray,dimtot,0.0,timestepcovariance,fixedseed); for(int i=0;i(temparray); } ISSM_MPI_Bcast(noiseterms,dimtot,ISSM_MPI_DOUBLE,0,IssmComm::GetComm()); femmodel->parameters->SetParam(noiseterms,dimtot,StochasticForcingNoisetermsEnum); } else{ IssmDouble* temparray = NULL; femmodel->parameters->FindParam(&temparray,&N,StochasticForcingNoisetermsEnum); _assert_(N==dimtot); for(int i=0;i(temparray); } int i=0; for(int j=0;j(dimensions[j]); for(int k=0;kelements->objects){ Element* element = xDynamicCast(object); int numvertices = element->GetNumberOfVertices(); IssmDouble* noise_element = xNew(numvertices); element->GetInputValue(&dimensionid,dimenum_type); for(int i=0;iAddInput(noiseenum_type,noise_element,P0Enum); xDelete(noise_element); } } else{ switch(fields[j]){ case SMBarmaEnum: case FrontalForcingsRignotarmaEnum: case BasalforcingsDeepwaterMeltingRatearmaEnum: case FrontalForcingsSubglacialDischargearmaEnum: /*Already done above*/ break; case BasalforcingsSpatialDeepwaterMeltingRateEnum: /*Delete BasalforcingsSpatialDeepwaterMeltingRateEnum at previous time step (required if it is transient)*/ femmodel->inputs->DeleteInput(BasalforcingsSpatialDeepwaterMeltingRateEnum); for(Object* &object:femmodel->elements->objects){ Element* element = xDynamicCast(object); int numvertices = element->GetNumberOfVertices(); IssmDouble baselinedeepwatermelt; IssmDouble deepwatermelt_tot[numvertices]; Input* baselinedeepwatermelt_input = NULL; baselinedeepwatermelt_input = element->GetInput(BaselineBasalforcingsSpatialDeepwaterMeltingRateEnum); _assert_(baselinedeepwatermelt_input); element->GetInputValue(&dimensionid,StochasticForcingDefaultIdEnum); Gauss* gauss = element->NewGauss(); for(int i=0;iGaussVertex(i); baselinedeepwatermelt_input->GetInputValue(&baselinedeepwatermelt,gauss); deepwatermelt_tot[i] = baselinedeepwatermelt+noisefield[dimensionid]; } element->AddInput(BasalforcingsSpatialDeepwaterMeltingRateEnum,&deepwatermelt_tot[0],P1DGEnum); delete gauss; } break; case DefaultCalvingEnum: /*Delete CalvingCalvingrateEnum at previous time step (required if it is transient)*/ femmodel->inputs->DeleteInput(CalvingCalvingrateEnum); for(Object* &object:femmodel->elements->objects){ Element* element = xDynamicCast(object); int numvertices = element->GetNumberOfVertices(); IssmDouble baselinecalvingrate; IssmDouble calvingrate_tot[numvertices]; Input* baselinecalvingrate_input = NULL; baselinecalvingrate_input = element->GetInput(BaselineCalvingCalvingrateEnum); _assert_(baselinecalvingrate_input); element->GetInputValue(&dimensionid,StochasticForcingDefaultIdEnum); Gauss* gauss = element->NewGauss(); for(int i=0;iGaussVertex(i); baselinecalvingrate_input->GetInputValue(&baselinecalvingrate,gauss); calvingrate_tot[i] = max(0.0,baselinecalvingrate+noisefield[dimensionid]); } element->AddInput(CalvingCalvingrateEnum,&calvingrate_tot[0],P1DGEnum); delete gauss; } break; case FloatingMeltRateEnum: /*Delete BasalforcingsFloatingiceMeltingRateEnum at previous time step (required if it is transient)*/ femmodel->inputs->DeleteInput(BasalforcingsFloatingiceMeltingRateEnum); for(Object* &object:femmodel->elements->objects){ Element* element = xDynamicCast(object); int numvertices = element->GetNumberOfVertices(); IssmDouble baselinefloatingicemeltrate; IssmDouble floatingicemeltrate_tot[numvertices]; Input* baselinefloatingicemeltrate_input = NULL; baselinefloatingicemeltrate_input = element->GetInput(BaselineBasalforcingsFloatingiceMeltingRateEnum); _assert_(baselinefloatingicemeltrate_input); element->GetInputValue(&dimensionid,StochasticForcingDefaultIdEnum); Gauss* gauss = element->NewGauss(); for(int i=0;iGaussVertex(i); baselinefloatingicemeltrate_input->GetInputValue(&baselinefloatingicemeltrate,gauss); /*No check for positive melt rate because basal accretion is allowed*/ floatingicemeltrate_tot[i] = baselinefloatingicemeltrate+noisefield[dimensionid]; } element->AddInput(BasalforcingsFloatingiceMeltingRateEnum,&floatingicemeltrate_tot[0],P1DGEnum); delete gauss; } break; case SMBforcingEnum: /*Delete SmbMassBalanceEnum at previous time step (required if it is transient)*/ femmodel->inputs->DeleteInput(SmbMassBalanceEnum); for(Object* &object:femmodel->elements->objects){ Element* element = xDynamicCast(object); int numvertices = element->GetNumberOfVertices(); IssmDouble baselinesmb; IssmDouble smb_tot[numvertices]; Input* baselinesmb_input = NULL; baselinesmb_input = element->GetInput(BaselineSmbMassBalanceEnum); _assert_(baselinesmb_input); element->GetInputValue(&dimensionid,StochasticForcingDefaultIdEnum); Gauss* gauss = element->NewGauss(); for(int i=0;iGaussVertex(i); baselinesmb_input->GetInputValue(&baselinesmb,gauss); smb_tot[i] = baselinesmb+noisefield[dimensionid]; } element->AddInput(SmbMassBalanceEnum,&smb_tot[0],P1DGEnum); delete gauss; } break; case FrictionWaterPressureEnum: /*Specify that WaterPressure is stochastic*/ femmodel->parameters->SetParam(true,StochasticForcingIsWaterPressureEnum); for(Object* &object:femmodel->elements->objects){ Element* element = xDynamicCast(object); int numvertices = element->GetNumberOfVertices(); IssmDouble p_water_deterministic[numvertices]; IssmDouble p_water[numvertices]; element->GetInputValue(&dimensionid,StochasticForcingDefaultIdEnum); element->SubglacialWaterPressure(FrictionWaterPressureEnum); element->GetInputListOnVertices(&p_water_deterministic[0],FrictionWaterPressureEnum); for(int i=0;iAddInput(FrictionWaterPressureEnum,p_water,P1DGEnum); } break; default: _error_("Field "<(noisefield); } /*Cleanup*/ xDelete(fields); xDelete(dimensions); xDelete(covariance); xDelete(timecovariance); xDelete(timestepcovariance); xDelete(noiseterms); }/*}}}*/