- Timestamp:
- 05/14/21 17:27:17 (4 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
issm/trunk-jpl/src/c/analyses/SealevelchangeAnalysis.cpp
r26242 r26272 80 80 81 81 int nl; 82 int ntimesteps; 82 83 IssmDouble* love_h=NULL; 83 84 IssmDouble* love_k=NULL; … … 86 87 IssmDouble* love_tk=NULL; 87 88 IssmDouble* love_tl=NULL; 89 IssmDouble* love_timefreq=NULL; 90 bool love_istime=true; 88 91 int externalnature=0; 89 92 int isexternal=0; … … 91 94 IssmDouble* G_rigid = NULL; 92 95 IssmDouble* G_rigid_local = NULL; 93 IssmDouble* G_elastic = NULL; 94 IssmDouble* G_elastic_local = NULL; 95 IssmDouble* U_elastic = NULL; 96 IssmDouble* U_elastic_local = NULL; 97 IssmDouble* H_elastic = NULL; 98 IssmDouble* H_elastic_local = NULL; 96 IssmDouble* G_viscoelastic = NULL; 97 IssmDouble* G_viscoelastic_interpolated = NULL; 98 IssmDouble* G_viscoelastic_local = NULL; 99 IssmDouble* U_viscoelastic = NULL; 100 IssmDouble* U_viscoelastic_interpolated = NULL; 101 IssmDouble* U_viscoelastic_local = NULL; 102 IssmDouble* H_viscoelastic = NULL; 103 IssmDouble* H_viscoelastic_interpolated= NULL; 104 IssmDouble* H_viscoelastic_local = NULL; 99 105 int M,m,lower_row,upper_row; 100 106 IssmDouble degacc=.01; 107 IssmDouble timeacc; 101 108 IssmDouble planetradius=0; 102 109 IssmDouble planetarea=0; 103 110 bool rigid=false; 104 111 bool elastic=false; 112 bool viscous=false; 105 113 bool rotation=false; 114 int ndeg; 115 int horiz; 116 117 bool istime=true; 118 IssmDouble start_time,final_time; 119 int nt,precomputednt; 106 120 107 121 int numoutputs; … … 120 134 IssmDouble* bslcocean_partition=NULL; 121 135 int npartice,nparthydro,npartocean,nel; 122 136 int grdmodel; 123 137 124 138 /*some constant parameters: */ … … 134 148 parameters->AddObject(iomodel->CopyConstantObject("md.solidearth.settings.horiz",SolidearthSettingsHorizEnum)); 135 149 parameters->AddObject(iomodel->CopyConstantObject("md.solidearth.settings.elastic",SolidearthSettingsElasticEnum)); 150 parameters->AddObject(iomodel->CopyConstantObject("md.solidearth.settings.viscous",SolidearthSettingsViscousEnum)); 136 151 parameters->AddObject(iomodel->CopyConstantObject("md.solidearth.settings.rotation",SolidearthSettingsRotationEnum)); 137 152 parameters->AddObject(iomodel->CopyConstantObject("md.solidearth.rotational.equatorialmoi",RotationalEquatorialMoiEnum)); … … 211 226 } 212 227 213 /*Deal with elasticity {{{*/ 214 iomodel->FetchData(&rigid,"md.solidearth.settings.rigid"); 215 iomodel->FetchData(&elastic,"md.solidearth.settings.elastic"); 216 iomodel->FetchData(&rotation,"md.solidearth.settings.rotation"); 217 218 if(elastic | rigid){ 219 /*compute green functions for a range of angles*/ 220 iomodel->FetchData(°acc,"md.solidearth.settings.degacc"); 221 M=reCast<int,IssmDouble>(180./degacc+1.); 222 } 223 224 /*love numbers: */ 225 if(elastic){ 226 iomodel->FetchData(&love_h,&nl,NULL,"md.solidearth.lovenumbers.h"); 227 iomodel->FetchData(&love_k,&nl,NULL,"md.solidearth.lovenumbers.k"); 228 iomodel->FetchData(&love_l,&nl,NULL,"md.solidearth.lovenumbers.l"); 229 iomodel->FetchData(&love_th,&nl,NULL,"md.solidearth.lovenumbers.th"); 230 iomodel->FetchData(&love_tk,&nl,NULL,"md.solidearth.lovenumbers.tk"); 231 iomodel->FetchData(&love_tl,&nl,NULL,"md.solidearth.lovenumbers.tl"); 232 233 parameters->AddObject(new DoubleMatParam(LoadLoveHEnum,love_h,nl,1)); 234 parameters->AddObject(new DoubleMatParam(LoadLoveKEnum,love_k,nl,1)); 235 parameters->AddObject(new DoubleMatParam(LoadLoveLEnum,love_l,nl,1)); 236 parameters->AddObject(new DoubleMatParam(TidalLoveHEnum,love_th,nl,1)); 237 parameters->AddObject(new DoubleMatParam(TidalLoveKEnum,love_tk,nl,1)); 238 parameters->AddObject(new DoubleMatParam(TidalLoveLEnum,love_tl,nl,1)); 239 240 // AD performance is sensitive to calls to ensurecontiguous. 241 // // Providing "t" will cause ensurecontiguous to be called. 242 #ifdef _HAVE_AD_ 243 G_elastic=xNew<IssmDouble>(M,"t"); 244 U_elastic=xNew<IssmDouble>(M,"t"); 245 H_elastic=xNew<IssmDouble>(M,"t"); 246 #else 247 G_elastic=xNew<IssmDouble>(M); 248 U_elastic=xNew<IssmDouble>(M); 249 H_elastic=xNew<IssmDouble>(M); 250 #endif 251 } 252 if(rigid){ 253 #ifdef _HAVE_AD_ 254 G_rigid=xNew<IssmDouble>(M,"t"); 255 #else 256 G_rigid=xNew<IssmDouble>(M); 257 #endif 258 } 259 260 if(rotation)parameters->AddObject(iomodel->CopyConstantObject("md.solidearth.lovenumbers.tk2secular",TidalLoveK2SecularEnum)); 261 262 if(rigid | elastic){ 263 264 /*compute combined legendre + love number (elastic green function:*/ 265 m=DetermineLocalSize(M,IssmComm::GetComm()); 266 GetOwnershipBoundariesFromRange(&lower_row,&upper_row,m,IssmComm::GetComm()); 267 } 268 if(elastic){ 269 #ifdef _HAVE_AD_ 270 G_elastic_local=xNew<IssmDouble>(m,"t"); 271 U_elastic_local=xNew<IssmDouble>(m,"t"); 272 H_elastic_local=xNew<IssmDouble>(m,"t"); 273 #else 274 G_elastic_local=xNew<IssmDouble>(m); 275 U_elastic_local=xNew<IssmDouble>(m); 276 H_elastic_local=xNew<IssmDouble>(m); 277 #endif 278 } 279 if(rigid){ 280 #ifdef _HAVE_AD_ 281 G_rigid_local=xNew<IssmDouble>(m,"t"); 282 #else 283 G_rigid_local=xNew<IssmDouble>(m); 284 #endif 285 } 286 287 if(rigid){ 288 for(int i=lower_row;i<upper_row;i++){ 289 IssmDouble alpha,x; 290 alpha= reCast<IssmDouble>(i)*degacc * PI / 180.0; 291 G_rigid_local[i-lower_row]= .5/sin(alpha/2.0); 292 } 293 } 294 if(elastic){ 295 for(int i=lower_row;i<upper_row;i++){ 296 IssmDouble alpha,x; 297 alpha= reCast<IssmDouble>(i)*degacc * PI / 180.0; 298 299 G_elastic_local[i-lower_row]= (love_k[nl-1]-love_h[nl-1])*G_rigid_local[i-lower_row]; 300 U_elastic_local[i-lower_row]= (love_h[nl-1])*G_rigid_local[i-lower_row]; 301 H_elastic_local[i-lower_row]= 0; 302 IssmDouble Pn = 0.; 303 IssmDouble Pn1 = 0.; 304 IssmDouble Pn2 = 0.; 305 IssmDouble Pn_p = 0.; 306 IssmDouble Pn_p1 = 0.; 307 IssmDouble Pn_p2 = 0.; 308 309 for (int n=0;n<nl;n++) { 310 IssmDouble deltalove_G; 311 IssmDouble deltalove_U; 312 313 deltalove_G = (love_k[n]-love_k[nl-1]-love_h[n]+love_h[nl-1]); 314 deltalove_U = (love_h[n]-love_h[nl-1]); 315 316 /*compute legendre polynomials: P_n(cos\theta) & d P_n(cos\theta)/ d\theta: */ 317 if(n==0){ 318 Pn=1; 319 Pn_p=0; 228 parameters->FindParam(&grdmodel,GrdModelEnum); 229 if(grdmodel!=IvinsEnum){ 230 /*Deal with elasticity {{{*/ 231 iomodel->FetchData(&rigid,"md.solidearth.settings.rigid"); 232 iomodel->FetchData(&elastic,"md.solidearth.settings.elastic"); 233 iomodel->FetchData(&viscous,"md.solidearth.settings.viscous"); 234 iomodel->FetchData(&rotation,"md.solidearth.settings.rotation"); 235 iomodel->FetchData(&horiz,"md.solidearth.settings.horiz"); 236 237 if(rigid){ 238 /*compute green functions for a range of angles*/ 239 iomodel->FetchData(°acc,"md.solidearth.settings.degacc"); 240 M=reCast<int,IssmDouble>(180./degacc+1.); 241 } 242 243 /*love numbers: */ 244 if(viscous || elastic){ 245 int dummy; 246 247 iomodel->FetchData(&timeacc,"md.solidearth.settings.timeacc"); 248 iomodel->FetchData(&start_time,"md.timestepping.start_time"); 249 iomodel->FetchData(&final_time,"md.timestepping.final_time"); 250 iomodel->FetchData(&love_istime,"md.solidearth.lovenumbers.istime"); 251 iomodel->FetchData(&love_timefreq,&precomputednt,&dummy,"md.solidearth.lovenumbers.timefreq"); 252 iomodel->FetchData(&love_h,&ndeg,&precomputednt,"md.solidearth.lovenumbers.h"); 253 iomodel->FetchData(&love_k,&ndeg,&precomputednt,"md.solidearth.lovenumbers.k"); 254 iomodel->FetchData(&love_l,&ndeg,&precomputednt,"md.solidearth.lovenumbers.l"); 255 iomodel->FetchData(&love_th,&ndeg,&precomputednt,"md.solidearth.lovenumbers.th"); 256 iomodel->FetchData(&love_tk,&ndeg,&precomputednt,"md.solidearth.lovenumbers.tk"); 257 iomodel->FetchData(&love_tl,&ndeg,&precomputednt,"md.solidearth.lovenumbers.tl"); 258 259 parameters->AddObject(new DoubleParam(SolidearthSettingsTimeAccEnum,timeacc)); 260 parameters->AddObject(new DoubleMatParam(LoadLoveHEnum,love_h,ndeg,precomputednt)); 261 parameters->AddObject(new DoubleMatParam(LoadLoveKEnum,love_k,ndeg,precomputednt)); 262 parameters->AddObject(new DoubleMatParam(LoadLoveLEnum,love_l,ndeg,precomputednt)); 263 parameters->AddObject(new DoubleMatParam(TidalLoveHEnum,love_th,ndeg,precomputednt)); 264 parameters->AddObject(new DoubleMatParam(TidalLoveKEnum,love_tk,ndeg,precomputednt)); 265 parameters->AddObject(new DoubleMatParam(TidalLoveLEnum,love_tl,ndeg,precomputednt)); 266 parameters->AddObject(new DoubleMatParam(LoveTimeFreqEnum,love_timefreq,precomputednt,1)); 267 parameters->AddObject(new BoolParam(LoveIsTimeEnum,love_istime)); 268 269 // AD performance is sensitive to calls to ensurecontiguous. 270 // // Providing "t" will cause ensurecontiguous to be called. 271 if(viscous){ 272 IssmDouble* stacktimes=NULL; 273 ntimesteps=precomputednt; 274 nt=reCast<int>((final_time-start_time)/timeacc)+1; 275 276 parameters->AddObject(new IntParam(StackNumStepsEnum,nt)); 277 /*Initialize stack times:*/ 278 stacktimes=xNew<IssmDouble>(nt); 279 for(int t=0;t<nt;t++){ 280 stacktimes[t]=start_time+timeacc*t; 320 281 } 321 else if(n==1){ 322 Pn = cos(alpha); 323 Pn_p = 1; 282 parameters->AddObject(new DoubleVecParam(StackTimesEnum,stacktimes,nt)); 283 parameters->AddObject(new IntParam(StackIndexEnum,0)); 284 xDelete<IssmDouble>(stacktimes); 285 } 286 else { 287 ntimesteps=1; 288 nt=1; 289 } 290 291 #ifdef _HAVE_AD_ 292 G_viscoelastic=xNew<IssmDouble>(M*ntimesteps,"t"); 293 U_viscoelastic=xNew<IssmDouble>(M*ntimesteps,"t"); 294 if(horiz)H_viscoelastic=xNew<IssmDouble>(M*ntimesteps,"t"); 295 #else 296 G_viscoelastic=xNew<IssmDouble>(M*ntimesteps); 297 U_viscoelastic=xNew<IssmDouble>(M*ntimesteps); 298 if(horiz)H_viscoelastic=xNew<IssmDouble>(M*ntimesteps); 299 #endif 300 } 301 if(rigid){ 302 #ifdef _HAVE_AD_ 303 G_rigid=xNew<IssmDouble>(M,"t"); 304 #else 305 G_rigid=xNew<IssmDouble>(M); 306 #endif 307 } 308 309 if(rotation)parameters->AddObject(iomodel->CopyConstantObject("md.solidearth.lovenumbers.tk2secular",TidalLoveK2SecularEnum)); 310 311 if(rigid){ 312 313 /*compute combined legendre + love number (elastic green function:*/ 314 m=DetermineLocalSize(M,IssmComm::GetComm()); 315 GetOwnershipBoundariesFromRange(&lower_row,&upper_row,m,IssmComm::GetComm()); 316 } 317 if(viscous | elastic){ 318 #ifdef _HAVE_AD_ 319 G_viscoelastic_local=xNew<IssmDouble>(m*ntimesteps,"t"); 320 U_viscoelastic_local=xNew<IssmDouble>(m*ntimesteps,"t"); 321 if(horiz)H_viscoelastic_local=xNew<IssmDouble>(m*ntimesteps,"t"); 322 #else 323 G_viscoelastic_local=xNew<IssmDouble>(m*ntimesteps); 324 U_viscoelastic_local=xNew<IssmDouble>(m*ntimesteps); 325 if(horiz)H_viscoelastic_local=xNew<IssmDouble>(m*ntimesteps); 326 #endif 327 } 328 if(rigid){ 329 #ifdef _HAVE_AD_ 330 G_rigid_local=xNew<IssmDouble>(m,"t"); 331 #else 332 G_rigid_local=xNew<IssmDouble>(m); 333 #endif 334 } 335 336 if(rigid){ 337 for(int i=lower_row;i<upper_row;i++){ 338 IssmDouble alpha,x; 339 alpha= reCast<IssmDouble>(i)*degacc * PI / 180.0; 340 G_rigid_local[i-lower_row]= .5/sin(alpha/2.0); 341 } 342 } 343 if(viscous | elastic){ 344 for(int i=lower_row;i<upper_row;i++){ 345 IssmDouble alpha,x; 346 alpha= reCast<IssmDouble>(i)*degacc * PI / 180.0; 347 348 for(int t=0;t<ntimesteps;t++){ 349 G_viscoelastic_local[(i-lower_row)*ntimesteps+t]= (love_k[(ndeg-1)*precomputednt+t]-love_h[(ndeg-1)*precomputednt+t])*G_rigid_local[i-lower_row]; 350 U_viscoelastic_local[(i-lower_row)*ntimesteps+t]= (love_h[(ndeg-1)*precomputednt+t])*G_rigid_local[i-lower_row]; 351 if(horiz)H_viscoelastic_local[(i-lower_row)*ntimesteps+t]= 0; 324 352 } 325 else{ 326 Pn = ( (2*n-1)*cos(alpha)*Pn1 - (n-1)*Pn2 ) /n; 327 Pn_p = ( (2*n-1)*(Pn1+cos(alpha)*Pn_p1) - (n-1)*Pn_p2 ) /n; 353 354 IssmDouble Pn = 0.; 355 IssmDouble Pn1 = 0.; 356 IssmDouble Pn2 = 0.; 357 IssmDouble Pn_p = 0.; 358 IssmDouble Pn_p1 = 0.; 359 IssmDouble Pn_p2 = 0.; 360 361 for (int n=0;n<ndeg;n++) { 362 363 /*compute legendre polynomials: P_n(cos\theta) & d P_n(cos\theta)/ d\theta: */ 364 if(n==0){ 365 Pn=1; 366 Pn_p=0; 367 } 368 else if(n==1){ 369 Pn = cos(alpha); 370 Pn_p = 1; 371 } 372 else{ 373 Pn = ( (2*n-1)*cos(alpha)*Pn1 - (n-1)*Pn2 ) /n; 374 Pn_p = ( (2*n-1)*(Pn1+cos(alpha)*Pn_p1) - (n-1)*Pn_p2 ) /n; 375 } 376 Pn2=Pn1; Pn1=Pn; 377 Pn_p2=Pn_p1; Pn_p1=Pn_p; 378 379 for(int t=0;t<ntimesteps;t++){ 380 IssmDouble deltalove_G; 381 IssmDouble deltalove_U; 382 383 deltalove_G = (love_k[n*precomputednt+t]-love_k[(ndeg-1)*precomputednt+t]-love_h[n*precomputednt+t]+love_h[(ndeg-1)*precomputednt+t]); 384 deltalove_U = (love_h[n*precomputednt+t]-love_h[(ndeg-1)*precomputednt+t]); 385 386 G_viscoelastic_local[(i-lower_row)*ntimesteps+t] += deltalove_G*Pn; // gravitational potential 387 U_viscoelastic_local[(i-lower_row)*ntimesteps+t] += deltalove_U*Pn; // vertical (up) displacement 388 if(horiz)H_viscoelastic_local[(i-lower_row)*ntimesteps+t] += sin(alpha)*love_l[n*precomputednt+t]*Pn_p; // horizontal displacements 389 } 328 390 } 329 Pn2=Pn1; Pn1=Pn; 330 Pn_p2=Pn_p1; Pn_p1=Pn_p; 331 332 G_elastic_local[i-lower_row] += deltalove_G*Pn; // gravitational potential 333 U_elastic_local[i-lower_row] += deltalove_U*Pn; // vertical (up) displacement 334 H_elastic_local[i-lower_row] += sin(alpha)*love_l[n]*Pn_p; // horizontal displacements 335 } 336 } 337 } 338 if(rigid){ 339 340 /*merge G_elastic_local into G_elastic; U_elastic_local into U_elastic; H_elastic_local to H_elastic:{{{*/ 341 int* recvcounts=xNew<int>(IssmComm::GetSize()); 342 int* displs=xNew<int>(IssmComm::GetSize()); 343 344 //recvcounts: 345 ISSM_MPI_Allgather(&m,1,ISSM_MPI_INT,recvcounts,1,ISSM_MPI_INT,IssmComm::GetComm()); 346 347 /*displs: */ 348 ISSM_MPI_Allgather(&lower_row,1,ISSM_MPI_INT,displs,1,ISSM_MPI_INT,IssmComm::GetComm()); 349 350 /*All gather:*/ 351 ISSM_MPI_Allgatherv(G_rigid_local, m, ISSM_MPI_DOUBLE, G_rigid, recvcounts, displs, ISSM_MPI_DOUBLE,IssmComm::GetComm()); 352 if(elastic){ 353 ISSM_MPI_Allgatherv(G_elastic_local, m, ISSM_MPI_DOUBLE, G_elastic, recvcounts, displs, ISSM_MPI_DOUBLE,IssmComm::GetComm()); 354 ISSM_MPI_Allgatherv(U_elastic_local, m, ISSM_MPI_DOUBLE, U_elastic, recvcounts, displs, ISSM_MPI_DOUBLE,IssmComm::GetComm()); 355 ISSM_MPI_Allgatherv(H_elastic_local, m, ISSM_MPI_DOUBLE, H_elastic, recvcounts, displs, ISSM_MPI_DOUBLE,IssmComm::GetComm()); 356 } 357 358 /*free resources: */ 359 xDelete<int>(recvcounts); 360 xDelete<int>(displs); 361 362 /*Avoid singularity at 0: */ 363 G_rigid[0]=G_rigid[1]; 364 if(elastic){ 365 G_elastic[0]=G_elastic[1]; 366 U_elastic[0]=U_elastic[1]; 367 H_elastic[0]=H_elastic[1]; 368 } 369 370 371 /*Save our precomputed tables into parameters*/ 372 parameters->AddObject(new DoubleVecParam(SealevelchangeGRigidEnum,G_rigid,M)); 373 if(elastic){ 374 parameters->AddObject(new DoubleVecParam(SealevelchangeGElasticEnum,G_elastic,M)); 375 parameters->AddObject(new DoubleVecParam(SealevelchangeUElasticEnum,U_elastic,M)); 376 parameters->AddObject(new DoubleVecParam(SealevelchangeHElasticEnum,H_elastic,M)); 377 } 378 379 /*free resources: */ 380 xDelete<IssmDouble>(G_rigid); 381 xDelete<IssmDouble>(G_rigid_local); 382 if(elastic){ 383 xDelete<IssmDouble>(love_h); 384 xDelete<IssmDouble>(love_k); 385 xDelete<IssmDouble>(love_l); 386 xDelete<IssmDouble>(love_th); 387 xDelete<IssmDouble>(love_tk); 388 xDelete<IssmDouble>(love_tl); 389 xDelete<IssmDouble>(G_elastic); 390 xDelete<IssmDouble>(G_elastic_local); 391 xDelete<IssmDouble>(U_elastic); 392 xDelete<IssmDouble>(U_elastic_local); 393 xDelete<IssmDouble>(H_elastic); 394 xDelete<IssmDouble>(H_elastic_local); 395 } 396 } /*}}}*/ 397 398 /*Indicate we have not yet run the Geometry Core module: */ 399 parameters->AddObject(new BoolParam(SealevelchangeGeometryDoneEnum,false)); 400 /*}}}*/ 391 } 392 } 393 if(rigid){ 394 395 /*merge G_viscoelastic_local into G_viscoelastic; U_viscoelastic_local into U_viscoelastic; H_viscoelastic_local to H_viscoelastic:{{{*/ 396 int* recvcounts=xNew<int>(IssmComm::GetSize()); 397 int* displs=xNew<int>(IssmComm::GetSize()); 398 int rc; 399 int offset; 400 401 //deal with rigid first: 402 ISSM_MPI_Allgather(&m,1,ISSM_MPI_INT,recvcounts,1,ISSM_MPI_INT,IssmComm::GetComm()); 403 404 /*displs: */ 405 ISSM_MPI_Allgather(&lower_row,1,ISSM_MPI_INT,displs,1,ISSM_MPI_INT,IssmComm::GetComm()); 406 407 /*All gather:*/ 408 ISSM_MPI_Allgatherv(G_rigid_local, m, ISSM_MPI_DOUBLE, G_rigid, recvcounts, displs, ISSM_MPI_DOUBLE,IssmComm::GetComm()); 409 410 if(elastic){ 411 rc=m*ntimesteps; 412 offset=lower_row*ntimesteps; 413 ISSM_MPI_Allgather(&rc,1,ISSM_MPI_INT,recvcounts,1,ISSM_MPI_INT,IssmComm::GetComm()); 414 ISSM_MPI_Allgather(&offset,1,ISSM_MPI_INT,displs,1,ISSM_MPI_INT,IssmComm::GetComm()); 415 416 ISSM_MPI_Allgatherv(G_viscoelastic_local, m*ntimesteps, ISSM_MPI_DOUBLE, G_viscoelastic, recvcounts, displs, ISSM_MPI_DOUBLE,IssmComm::GetComm()); 417 ISSM_MPI_Allgatherv(U_viscoelastic_local, m*ntimesteps, ISSM_MPI_DOUBLE, U_viscoelastic, recvcounts, displs, ISSM_MPI_DOUBLE,IssmComm::GetComm()); 418 if(horiz)ISSM_MPI_Allgatherv(H_viscoelastic_local, m*ntimesteps, ISSM_MPI_DOUBLE, H_viscoelastic, recvcounts, displs, ISSM_MPI_DOUBLE,IssmComm::GetComm()); 419 } 420 421 /*free resources: */ 422 xDelete<int>(recvcounts); 423 xDelete<int>(displs); 424 425 426 427 /*Avoid singularity at 0: */ 428 G_rigid[0]=G_rigid[1]; 429 if(elastic){ 430 for(int t=0;t<ntimesteps;t++){ 431 G_viscoelastic[t]=G_viscoelastic[ntimesteps+t]; 432 U_viscoelastic[t]=U_viscoelastic[ntimesteps+t]; 433 if(horiz)H_viscoelastic[t]=H_viscoelastic[ntimesteps+t]; 434 } 435 } 436 437 438 439 /*Reinterpolate viscoelastic green kernels onto a regular gridded time 440 *with steps equal to timeacc:*/ 441 if(viscous){ 442 nt=reCast<int>((final_time-start_time)/timeacc)+1; 443 #ifdef _HAVE_AD_ 444 G_viscoelastic_interpolated=xNew<IssmDouble>(M*nt,"t"); 445 U_viscoelastic_interpolated=xNew<IssmDouble>(M*nt,"t"); 446 if(horiz)H_viscoelastic_interpolated=xNew<IssmDouble>(M*nt,"t"); 447 #else 448 G_viscoelastic_interpolated=xNew<IssmDouble>(M*nt); 449 U_viscoelastic_interpolated=xNew<IssmDouble>(M*nt); 450 if(horiz)H_viscoelastic_interpolated=xNew<IssmDouble>(M*nt); 451 #endif 452 453 for(int t=0;t<nt;t++){ 454 IssmDouble lincoeff; 455 IssmDouble viscoelastic_time=t*timeacc; 456 int timeindex2=-1; 457 458 /*Find a way to interpolate precomputed Gkernels to our solution time stepping:*/ 459 if(t!=0){ 460 for(int t2=0;t2<ntimesteps;t2++){ 461 if (viscoelastic_time<love_timefreq[t2]){ 462 timeindex2=t2-1; 463 if(timeindex2<0)_error_("Temporal Love numbers are computed with a time accuracy superior to the requested solution time step!"); 464 lincoeff=(viscoelastic_time-love_timefreq[t2-1])/(love_timefreq[t2]-love_timefreq[t2-1]); 465 break; 466 } 467 } 468 if(timeindex2==-1)_error_("Temporal love numbers should be extended in time to encompass the requested solution time interval!"); 469 } 470 else{ 471 timeindex2=0; 472 lincoeff=0; 473 } 474 475 for(int index=0;index<M;index++){ 476 477 int timeindex=index*nt+t; 478 int timepreindex= index*ntimesteps+timeindex2; 479 G_viscoelastic_interpolated[timeindex]+=(1-lincoeff)*G_viscoelastic[timepreindex]+lincoeff*G_viscoelastic[timepreindex+1]; 480 U_viscoelastic_interpolated[timeindex]+=(1-lincoeff)*U_viscoelastic[timepreindex]+lincoeff*U_viscoelastic[timepreindex+1]; 481 if(horiz)H_viscoelastic_interpolated[timeindex]+=(1-lincoeff)*H_viscoelastic[timepreindex]+lincoeff*H_viscoelastic[timepreindex+1]; 482 } 483 } 484 485 } 486 else if(elastic){ 487 nt=1; //in elastic, or if we run only rigid, we need only one step 488 #ifdef _HAVE_AD_ 489 G_viscoelastic_interpolated=G_viscoelastic; 490 U_viscoelastic_interpolated=U_viscoelastic; 491 if(horiz)H_viscoelastic_interpolated=H_viscoelastic; 492 #else 493 G_viscoelastic_interpolated=G_viscoelastic; 494 U_viscoelastic_interpolated=U_viscoelastic; 495 if(horiz)H_viscoelastic_interpolated=H_viscoelastic; 496 #endif 497 } 498 499 /*Save our precomputed tables into parameters*/ 500 parameters->AddObject(new DoubleVecParam(SealevelchangeGRigidEnum,G_rigid,M)); 501 if(viscous || elastic){ 502 parameters->AddObject(new DoubleVecParam(SealevelchangeGViscoElasticEnum,G_viscoelastic_interpolated,M*nt)); 503 parameters->AddObject(new DoubleVecParam(SealevelchangeUViscoElasticEnum,U_viscoelastic_interpolated,M*nt)); 504 if(horiz)parameters->AddObject(new DoubleVecParam(SealevelchangeHViscoElasticEnum,H_viscoelastic_interpolated,M*nt)); 505 } 506 507 /*free resources: */ 508 xDelete<IssmDouble>(G_rigid); 509 xDelete<IssmDouble>(G_rigid_local); 510 if(elastic){ 511 xDelete<IssmDouble>(love_h); 512 xDelete<IssmDouble>(love_k); 513 xDelete<IssmDouble>(love_l); 514 xDelete<IssmDouble>(love_th); 515 xDelete<IssmDouble>(love_tk); 516 xDelete<IssmDouble>(love_tl); 517 xDelete<IssmDouble>(G_viscoelastic); 518 xDelete<IssmDouble>(G_viscoelastic_local); 519 xDelete<IssmDouble>(U_viscoelastic); 520 xDelete<IssmDouble>(U_viscoelastic_local); 521 if(horiz){ 522 xDelete<IssmDouble>(H_viscoelastic); 523 xDelete<IssmDouble>(H_viscoelastic_local); 524 } 525 } 526 } /*}}}*/ 527 528 /*Indicate we have not yet run the Geometry Core module: */ 529 parameters->AddObject(new BoolParam(SealevelchangeGeometryDoneEnum,false)); 530 /*}}}*/ 531 } 401 532 402 533 /*Transitions:{{{ */
Note:
See TracChangeset
for help on using the changeset viewer.