Changeset 27232 for issm/trunk/src/c/classes/Elements/Tria.cpp
- Timestamp:
- 08/25/22 16:50:29 (3 years ago)
- Location:
- issm/trunk
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
issm/trunk
-
issm/trunk/src
- Property svn:mergeinfo changed
-
issm/trunk/src/c/classes/Elements/Tria.cpp
r27035 r27232 376 376 IssmDouble time; 377 377 IssmDouble coeff, indrate; 378 IssmDouble bed, bedrate = 1.0; 378 379 379 380 /*Retrieve all inputs and parameters we will need*/ … … 382 383 parameters->FindParam(&indrate,CalvingTestIndependentRateEnum,time); 383 384 385 Input *bs_input = this->GetInput(BedEnum);_assert_(bs_input); 384 386 Input* vx_input = this->GetInput(VxEnum); _assert_(vx_input); 385 387 Input* vy_input = this->GetInput(VyEnum); _assert_(vy_input); … … 399 401 lsf_slopey_input->GetInputValue(&dphidy,&gauss); 400 402 403 bs_input->GetInputValue(&bed,&gauss); 404 bedrate = (bed>0)?0.0:1.0; 405 401 406 vel=sqrt(vx*vx + vy*vy) + 1e-14; 402 407 dphi=sqrt(dphidx*dphidx+dphidy*dphidy)+ 1e-14; 403 408 404 calvingratex[iv]= coeff*vx + indrate*dphidx/dphi;405 calvingratey[iv]= coeff*vy + indrate*dphidy/dphi;409 calvingratex[iv]= coeff*vx + bedrate*indrate*dphidx/dphi; 410 calvingratey[iv]= coeff*vy + bedrate*indrate*dphidy/dphi; 406 411 calvingrate[iv] = sqrt(calvingratex[iv]*calvingratex[iv] + calvingratey[iv]*calvingratey[iv]); 407 412 } … … 835 840 IssmDouble lambda1,lambda2,ex,ey,vx,vy,vel; 836 841 IssmDouble sigma_vm[NUMVERTICES]; 837 IssmDouble B, sigma_max,sigma_max_floating,sigma_max_grounded,n;842 IssmDouble B, n; 838 843 IssmDouble epse_2,groundedice,bed,sealevel; 839 IssmDouble arate, rho_ice, rho_water, thickness , paramX, Hab;840 int use_parameter= 0;841 int nonlinear_law=0;842 IssmDouble theta, alpha, midp, gamma;844 IssmDouble arate, rho_ice, rho_water, thickness; 845 int use_parameter=-1; 846 IssmDouble gamma, theta, alpha, xoffset, yoffset; 847 IssmDouble vel_lower, vel_upper, vrate, truncateVrate; 843 848 844 849 /* Get node coordinates and dof list: */ … … 852 857 Input *bs_input = this->GetInput(BedEnum); _assert_(bs_input); 853 858 Input *H_input = this->GetInput(ThicknessEnum); _assert_(H_input); 854 Input *smax_fl_input = this->GetInput(CalvingStressThresholdFloatingiceEnum); _assert_(smax_fl_input);855 Input *smax_gr_input = this->GetInput(CalvingStressThresholdGroundediceEnum); _assert_(smax_gr_input);856 859 Input *n_input = this->GetInput(MaterialsRheologyNEnum); _assert_(n_input); 857 860 Input *sl_input = this->GetInput(SealevelEnum); _assert_(sl_input); … … 864 867 /* Use which parameter */ 865 868 this->FindParam(&use_parameter, CalvingUseParamEnum); 866 this->FindParam(&theta, CalvingScaleThetaEnum); 867 this->FindParam(&alpha, CalvingAmpAlphaEnum); 868 this->FindParam(&midp, CalvingMidpointEnum); 869 this->FindParam(&nonlinear_law, CalvingNonlinearLawEnum); 869 this->FindParam(&theta, CalvingThetaEnum); 870 this->FindParam(&alpha, CalvingAlphaEnum); 871 this->FindParam(&xoffset, CalvingXoffsetEnum); 872 this->FindParam(&yoffset, CalvingYoffsetEnum); 873 this->FindParam(&vel_lower, CalvingVelLowerboundEnum); 874 this->FindParam(&vel_upper, CalvingVelUpperboundEnum); 870 875 871 876 /* Start looping on the number of vertices: */ … … 882 887 bs_input->GetInputValue(&bed,gauss); 883 888 H_input->GetInputValue(&thickness,gauss); 884 smax_fl_input->GetInputValue(&sigma_max_floating,gauss);885 smax_gr_input->GetInputValue(&sigma_max_grounded,gauss);886 889 vel=sqrt(vx*vx+vy*vy)+1.e-14; 887 890 sl_input->GetInputValue(&sealevel,gauss); 888 891 arate_input->GetInputValue(&arate,gauss); 892 vrate = 1.0; 893 if (vel < vel_upper) vrate = vel / vel_upper; 889 894 890 895 /*Compute strain rate and viscosity: */ … … 904 909 sigma_vm[iv] = sqrt(3.) * B * pow(epse_2,1./(2.*n)); 905 910 906 /*Tensile stress threshold*/907 if(groundedice<0)908 sigma_max = sigma_max_floating;909 else910 sigma_max = sigma_max_grounded;911 912 911 switch (use_parameter) { 913 912 case 0: 914 /* bed elevation*/915 paramX = bed;913 /* 0 Linear: f(x) = y_{o} + \alpha (x+x_{o}) */ 914 gamma = yoffset = alpha * (bed+xoffset); 916 915 break; 917 916 case 1: 918 /* Height above floatation */ 919 if (bed>sealevel) paramX = 0.0; 920 else paramX = thickness - (rho_water/rho_ice) * (sealevel-bed); 917 /* 1 tanh: f(x)=y_{o}-\frac{\theta}{2}\tanh(\alpha(x+x_{o})) */ 918 gamma = yoffset - 0.5*theta*tanh(alpha*(bed+xoffset)); 921 919 break; 922 920 case 2: 923 /* Thicknese */ 924 paramX = thickness; 921 /* 2 tanh(thicknes): f(x)=y_{o}-\frac{\theta}{2}\tanh(\alpha(x+x_{o})) */ 922 gamma = yoffset - 0.5*theta*tanh(alpha*(-thickness+xoffset)); 923 break; 924 case 3: 925 /* 3 tanh(normal vel): f(x)=y_{o}-\frac{\theta}{2}\tanh(\alpha(x+x_{o})) */ 926 _error_("The normalized velocity is not supported yet!"); 927 gamma = yoffset - 0.5*theta*tanh(alpha*(vel+xoffset)); 925 928 break; 926 929 case 4: 927 /* bed elevation+linear curve fitting */ 928 paramX = bed; 930 /* 4 tanh(truncated vel): f(x)=y_{o}-\frac{\theta}{2}\tanh(\alpha(x+x_{o})) */ 931 truncateVrate = (min(vel_upper, max(vel_lower, vel))-vel_lower) / vel_upper; 932 gamma = 0.5*theta*(tanh(alpha*xoffset) - tanh(alpha*(truncateVrate+xoffset))); 929 933 break; 930 934 case -1: 931 /* use nothing, just the arate*/ 935 /* nothing, just the arate*/ 936 gamma = 1; 932 937 break; 933 938 default: … … 935 940 } 936 941 937 /* Compute the hyperbolic tangent function */ 938 if ((use_parameter>-0.5) & (use_parameter<3)) { 939 gamma = 0.5*theta*(1.0-tanh((paramX+midp)/alpha))+(1.0-theta); 940 if (gamma<0.0) gamma =0.0; 941 } 942 else if (use_parameter>=3) { 943 gamma = alpha*paramX + theta; 944 if (gamma > 1.0) gamma = 1.0; 945 if (gamma < 0.0) gamma = 0.0; 946 } 947 else gamma = 1; 942 /* set upper and lower bounds */ 943 if (gamma > 1.0) gamma = 1.0; 944 if (gamma < 0.0) gamma = 0.0; 945 if (bed >= sealevel) gamma = 0.0; 948 946 949 947 /*-------------------------------------------*/ 950 if (nonlinear_law) { 951 /*This von Mises type has too strong positive feedback with vel included 952 * calvingrate[iv] = (arate+sigma_vm[iv]*vel/sigma_max)*gamma; 953 */ 954 Hab = thickness - (rho_water/rho_ice) * (sealevel-bed); 955 if (Hab < 0.) Hab = 0.; 956 if (bed > sealevel) Hab = 0.; 957 958 calvingrate[iv] = (arate+Hab/sigma_max)*gamma; 959 } 948 if (use_parameter < 3) { 949 calvingrate[iv] = arate*gamma*vrate; 950 } 960 951 else { 961 952 calvingrate[iv] = arate*gamma; 962 953 } 963 954 } 964 965 955 /*Add input*/ 966 956 this->AddInput(CalvingCalvingrateEnum,&calvingrate[0],P1DGEnum); … … 2018 2008 else for(int i=0;i<NUMVERTICES;i++)weights[i]=0; 2019 2009 2020 /* free ressources:*/2010 /*Free resources:*/ 2021 2011 delete gauss; 2022 2012 … … 3905 3895 this->AddInput(enum_type,values,this->element_type); 3906 3896 3907 /*Free res sources:*/3897 /*Free resources:*/ 3908 3898 xDelete<IssmDouble>(values); 3909 3899 xDelete<int>(doflist); … … 6044 6034 pY->SetValues(gsize,indices,Y_values,ADD_VAL); 6045 6035 6046 /* free ressources:*/6036 /*Free resources:*/ 6047 6037 xDelete<int>(indices); 6048 6038 xDelete<IssmDouble>(U_values); xDelete<IssmDouble>(N_values); xDelete<IssmDouble>(E_values); … … 6206 6196 pEast->SetValues(gsize,indices,E_values,ADD_VAL); 6207 6197 6208 /* free ressources:*/6198 /*Free resources:*/ 6209 6199 xDelete<int>(indices); 6210 6200 xDelete<IssmDouble>(U_values); xDelete<IssmDouble>(N_values); xDelete<IssmDouble>(E_values); … … 6313 6303 } 6314 6304 6315 /*Free res sources: */6305 /*Free resources: */ 6316 6306 xDelete<IssmDouble>(hes); 6317 6307 xDelete<IssmDouble>(times); … … 6320 6310 } 6321 6311 /*}}}*/ 6322 void Tria::SealevelchangeGeometryInitial(IssmDouble* xxe, IssmDouble* yye, IssmDouble* zze, IssmDouble* areae ){ /*{{{*/6312 void Tria::SealevelchangeGeometryInitial(IssmDouble* xxe, IssmDouble* yye, IssmDouble* zze, IssmDouble* areae, int* lids){ /*{{{*/ 6323 6313 6324 6314 /*Declarations:{{{*/ … … 6342 6332 6343 6333 #ifdef _HAVE_RESTRICT_ 6344 IssmDouble* __restrict__ G=NULL;6345 IssmDouble* __restrict__ GU=NULL;6346 IssmDouble* __restrict__ GN=NULL;6347 IssmDouble* __restrict__ GE=NULL;6348 IssmDouble* __restrict__ G_viscoelastic_precomputed=NULL;6349 6334 IssmDouble* __restrict__ G_gravi_precomputed=NULL; 6350 IssmDouble* __restrict__ U_viscoelastic_precomputed=NULL;6351 IssmDouble* __restrict__ H_viscoelastic_precomputed=NULL;6352 6335 #else 6353 IssmDouble* G=NULL;6354 IssmDouble* GU=NULL;6355 IssmDouble* GN=NULL;6356 IssmDouble* GE=NULL;6357 IssmDouble* G_viscoelastic_precomputed=NULL;6358 6336 IssmDouble* G_gravi_precomputed=NULL; 6359 IssmDouble* U_viscoelastic_precomputed=NULL;6360 IssmDouble* H_viscoelastic_precomputed=NULL;6361 6337 #endif 6362 6338 … … 6364 6340 int index; 6365 6341 int M; 6342 IssmDouble degacc; 6366 6343 IssmDouble doubleindex,lincoef; 6367 6344 … … 6380 6357 /*Rotational:*/ 6381 6358 #ifdef _HAVE_RESTRICT_ 6359 IssmDouble* __restrict__ Grot=NULL; 6360 IssmDouble* __restrict__ GUrot=NULL; 6361 IssmDouble* __restrict__ GNrot=NULL; 6362 IssmDouble* __restrict__ GErot=NULL; 6382 6363 IssmDouble* __restrict__ tide_love_h = NULL; 6383 6364 IssmDouble* __restrict__ tide_love_k = NULL; … … 6386 6367 IssmDouble* __restrict__ LoveRotU = NULL; 6387 6368 IssmDouble* __restrict__ LoveRothoriz = NULL; 6388 IssmDouble* __restrict__ Grot = NULL; 6389 IssmDouble* __restrict__ GUrot = NULL; 6390 IssmDouble* __restrict__ GNrot = NULL; 6391 IssmDouble* __restrict__ GErot = NULL; 6369 int* __restrict__ AplhaIndex = NULL; 6370 int* __restrict__ AzimuthIndex = NULL; 6392 6371 #else 6372 IssmDouble* Grot=NULL; 6373 IssmDouble* GUrot=NULL; 6374 IssmDouble* GNrot=NULL; 6375 IssmDouble* GErot=NULL; 6393 6376 IssmDouble* tide_love_h = NULL; 6394 6377 IssmDouble* tide_love_k = NULL; … … 6397 6380 IssmDouble* LoveRotU = NULL; 6398 6381 IssmDouble* LoveRothoriz = NULL; 6399 IssmDouble* Grot = NULL; 6400 IssmDouble* GUrot = NULL; 6401 IssmDouble* GNrot = NULL; 6402 IssmDouble* GErot = NULL; 6382 int* AlphaIndex = NULL; 6383 int* AzimuthIndex = NULL; 6403 6384 #endif 6404 6385 … … 6439 6420 6440 6421 /*Recover precomputed green function kernels:{{{*/ 6441 DoubleVecParam* parameter = static_cast<DoubleVecParam*>(this->parameters->FindParamObject(SealevelchangeGSelfAttractionEnum)); _assert_(parameter); 6442 parameter->GetParameterValueByPointer((IssmDouble**)&G_gravi_precomputed,&M); 6443 6422 parameters->FindParam(°acc,SolidearthSettingsDegreeAccuracyEnum); 6423 M=reCast<int,IssmDouble>(180.0/degacc+1.); 6424 6425 DoubleVecParam* parameter; 6444 6426 if(computeelastic){ 6445 parameter = static_cast<DoubleVecParam*>(this->parameters->FindParamObject(SealevelchangeGViscoElasticEnum)); _assert_(parameter);6446 parameter->GetParameterValueByPointer((IssmDouble**)&G_viscoelastic_precomputed,NULL);6447 6448 parameter = static_cast<DoubleVecParam*>(this->parameters->FindParamObject(SealevelchangeUViscoElasticEnum)); _assert_(parameter);6449 parameter->GetParameterValueByPointer((IssmDouble**)&U_viscoelastic_precomputed,NULL);6450 6451 if(horiz){6452 parameter = static_cast<DoubleVecParam*>(this->parameters->FindParamObject(SealevelchangeHViscoElasticEnum)); _assert_(parameter);6453 parameter->GetParameterValueByPointer((IssmDouble**)&H_viscoelastic_precomputed,NULL);6454 }6455 6456 6427 if(computerotation){ 6457 6428 parameter = static_cast<DoubleVecParam*>(this->parameters->FindParamObject(SealevelchangeTidalH2Enum)); _assert_(parameter); … … 6489 6460 } 6490 6461 6491 constant=3/rho_earth/planetarea; 6492 6493 G=xNewZeroInit<IssmDouble>(3*nel*nt); 6494 if(computeelastic){ 6495 GU=xNewZeroInit<IssmDouble>(3*nel*nt); 6496 if(horiz){ 6497 GN=xNewZeroInit<IssmDouble>(3*nel*nt); 6498 GE=xNewZeroInit<IssmDouble>(3*nel*nt); 6499 } 6500 } 6501 6502 for(int e=0;e<nel;e++){ 6503 ratioe=constant*areae[e]; 6504 for (int i=0;i<3;i++){ 6505 IssmDouble alpha; 6506 IssmDouble delPhi,delLambda; 6507 /*recovers info for this element and vertex:*/ 6508 IssmDouble late= asin(zze[e]/sqrt( pow(xxe[e],2.0)+ pow(yye[e],2.0)+ pow(zze[e],2.0))); 6509 IssmDouble longe= atan2(yye[e],xxe[e]); 6510 6511 lati=latitude[i]; 6512 longi=longitude[i]; 6513 6514 /*Computes alpha angle between centroid and current vertex, and indexes alpha in precomputed tables: */ 6515 delPhi=fabs(lati-late); delLambda=fabs(longi-longe); if (delLambda>M_PI)delLambda=2*M_PI-delLambda; 6516 alpha=2.*asin(sqrt(pow(sin(delPhi/2),2)+cos(lati)*cos(late)*pow(sin(delLambda/2),2))); 6517 doubleindex=alpha/M_PI*reCast<IssmDouble,int>(M-1); //maps 0<alpha<PI on [0:M-1] 6518 index=reCast<int,IssmDouble>(doubleindex); //truncates doubleindex to integer part 6519 _assert_(index>=0 && index<M); 6520 6521 lincoef=doubleindex-index; //where between index and index+1 is alpha 6522 if (index==M-1){ //avoids out of bound case 6523 index-=1; 6524 lincoef=1; 6525 } 6526 6527 if(horiz){ 6528 /*Compute azimuths, both north and east components: */ 6529 x = xyz_list[i][0]; y = xyz_list[i][1]; z = xyz_list[i][2]; 6530 if(lati==M_PI/2){ 6531 x=1e-12; y=1e-12; 6462 AlphaIndex=xNewZeroInit<int>(3*nel); 6463 if (horiz) AzimuthIndex=xNewZeroInit<int>(3*nel); 6464 int intmax=pow(2,16)-1; 6465 6466 6467 for (int i=0;i<3;i++){ 6468 if(lids[this->vertices[i]->lid]==this->lid){ 6469 for(int e=0;e<nel;e++){ 6470 IssmDouble alpha; 6471 IssmDouble delPhi,delLambda; 6472 /*recovers info for this element and vertex:*/ 6473 IssmDouble late= asin(zze[e]/sqrt( pow(xxe[e],2.0)+ pow(yye[e],2.0)+ pow(zze[e],2.0))); 6474 IssmDouble longe= atan2(yye[e],xxe[e]); 6475 6476 lati=latitude[i]; 6477 longi=longitude[i]; 6478 6479 /*Computes alpha angle between centroid and current vertex, and indexes alpha in precomputed tables: */ 6480 delPhi=fabs(lati-late); delLambda=fabs(longi-longe); if (delLambda>M_PI)delLambda=2*M_PI-delLambda; 6481 alpha=2.*asin(sqrt(pow(sin(delPhi/2),2)+cos(lati)*cos(late)*pow(sin(delLambda/2),2))); 6482 doubleindex=alpha/M_PI*reCast<IssmDouble,int>(M-1); //maps 0<alpha<PI on [0:M-1] 6483 index=reCast<int,IssmDouble>(doubleindex); //truncates doubleindex to integer part 6484 if ((doubleindex-index)>=0.5) index+=1; //nearest neighbour 6485 _assert_(index>=0 && index<M); 6486 6487 if(horiz){ 6488 /*Compute azimuths*/ 6489 dx=cos(lati)*sin(late)-sin(lati)*cos(late)*cos(longe-longi); 6490 dy=sin(longe-longi)*cos(late); 6491 //angle between horiz motion and North, remapped from a double on [0,2*pi] to a int [0,intmax] 6492 AzimuthIndex[i*nel+e]=reCast<int,IssmDouble>(intmax*(atan2(dy,dx)/2/M_PI)); 6532 6493 } 6533 if(lati==-M_PI/2){ 6534 x=1e-12; y=1e-12; 6535 } 6536 dx = xxe[e]-x; dy = yye[e]-y; dz = zze[e]-z; 6537 N_azim = (-z*x*dx-z*y*dy+(pow(x,2)+pow(y,2))*dz) /pow((pow(x,2)+pow(y,2))*(pow(x,2)+pow(y,2)+pow(z,2))*(pow(dx,2)+pow(dy,2)+pow(dz,2)),0.5); 6538 E_azim = (-y*dx+x*dy) /pow((pow(x,2)+pow(y,2))*(pow(dx,2)+pow(dy,2)+pow(dz,2)),0.5); 6539 } 6540 6541 for(int t=0;t<nt;t++){ 6542 int timeindex=i*nel*nt+e*nt+t; 6543 6544 /*Rigid earth gravitational perturbation: */ 6545 G[timeindex]+=G_gravi_precomputed[index+0]*(1.-lincoef) 6546 +G_gravi_precomputed[index+1]*lincoef; //linear interpolation 6547 6548 /*Find a way to interpolate precomputed Gkernels to our solution time stepping:*/ 6549 if(computeelastic){ 6550 G[timeindex]+=G_viscoelastic_precomputed[(index+0)*nt+t]*(1.-lincoef) 6551 +G_viscoelastic_precomputed[(index+1)*nt+t]*lincoef; //linear interpolation 6552 } 6553 G[timeindex]=G[timeindex]*ratioe; 6554 6555 /*Elastic components:*/ 6556 if(computeelastic){ 6557 GU[timeindex] = ratioe *(U_viscoelastic_precomputed[(index+0)*nt+t]*(1.-lincoef) 6558 +U_viscoelastic_precomputed[(index+1)*nt+t]*lincoef); 6559 if(horiz){ 6560 GN[timeindex] = N_azim*ratioe *(H_viscoelastic_precomputed[(index+0)*nt+t]*(1.-lincoef) 6561 +H_viscoelastic_precomputed[(index+1)*nt+t]*lincoef); 6562 GE[timeindex] = E_azim*ratioe *(H_viscoelastic_precomputed[(index+0)*nt+t]*(1.-lincoef) 6563 +H_viscoelastic_precomputed[(index+1)*nt+t]*lincoef); 6564 } 6565 } 6566 } //for(int t=0;t<nt;t++) 6494 AlphaIndex[i*nel+e]=index; 6495 } 6567 6496 } //for (int i=0;i<3;i++) 6568 6497 } //for(int e=0;e<nel;e++) 6569 6498 6570 6499 /*Add in inputs:*/ 6571 this->inputs->SetArrayInput(SealevelchangeGEnum,this->lid,G,nel*3*nt); 6572 if(computeelastic){ 6573 this->inputs->SetArrayInput(SealevelchangeGUEnum,this->lid,GU,nel*3*nt); 6574 if(horiz){ 6575 this->inputs->SetArrayInput(SealevelchangeGNEnum,this->lid,GN,nel*3*nt); 6576 this->inputs->SetArrayInput(SealevelchangeGEEnum,this->lid,GE,nel*3*nt); 6577 } 6578 } 6500 this->inputs->SetIntArrayInput(SealevelchangeAlphaIndexEnum,this->lid,AlphaIndex,nel*3); 6501 if(horiz) this->inputs->SetIntArrayInput(SealevelchangeAzimuthIndexEnum,this->lid,AzimuthIndex,nel*3); 6502 6579 6503 /*}}}*/ 6580 6504 /*Compute rotation kernel:{{{*/ … … 6583 6507 LoveRotRSL = xNewZeroInit<IssmDouble>(nt); 6584 6508 LoveRotU = xNewZeroInit<IssmDouble>(nt); 6585 LoveRothoriz= xNewZeroInit<IssmDouble>(nt);6509 if(horiz)LoveRothoriz= xNewZeroInit<IssmDouble>(nt); 6586 6510 Grot = xNewZeroInit<IssmDouble>(3*3*nt); //3 polar motion components * 3 vertices * number of time steps 6587 6511 GUrot = xNewZeroInit<IssmDouble>(3*3*nt); … … 6669 6593 } 6670 6594 } 6595 /*Free resources:*/ 6596 xDelete<IssmDouble>(LoveRotRSL); 6597 xDelete<IssmDouble>(LoveRotU); 6598 if(horiz)xDelete<IssmDouble>(LoveRothoriz); 6671 6599 } 6672 6600 /*}}}*/ … … 6690 6618 /*Free allocations:{{{*/ 6691 6619 #ifdef _HAVE_RESTRICT_ 6692 delete G; 6693 if(computeelastic){ 6694 delete GU; 6695 if(horiz){ 6696 delete GN; 6697 delete GE; 6698 } 6699 if(computerotation){ 6700 delete Grot; 6701 delete GUrot; 6702 if (horiz){ 6703 delete GNrot; 6704 delete GErot; 6705 } 6706 } 6707 } 6620 delete AlphaIndex; 6621 if(horiz) AzimuthIndex; 6622 6623 if(computerotation){ 6624 delete Grot; 6625 delete GUrot; 6626 if (horiz){ 6627 delete GNrot; 6628 delete GErot; 6629 } 6630 } 6631 6708 6632 #else 6709 xDelete(G); 6710 if(computeelastic){ 6711 xDelete(GU); 6712 if(horiz){ 6713 xDelete(GN); 6714 xDelete(GE); 6715 } 6716 if(computerotation){ 6717 xDelete(Grot); 6718 xDelete(GUrot); 6719 if (horiz){ 6720 xDelete(GNrot); 6721 xDelete(GErot); 6722 } 6633 xDelete<int>(AlphaIndex); 6634 if(horiz){ 6635 xDelete<int>(AzimuthIndex); 6636 } 6637 if(computerotation){ 6638 xDelete<IssmDouble>(Grot); 6639 xDelete<IssmDouble>(GUrot); 6640 if (horiz){ 6641 xDelete<IssmDouble>(GNrot); 6642 xDelete<IssmDouble>(GErot); 6723 6643 } 6724 6644 } 6725 6645 #endif 6646 /*}}}*/ 6647 return; 6648 6649 } 6650 /*}}}*/ 6651 6652 void Tria::SealevelchangeGeometrySubElementKernel(SealevelGeometry* slgeom){ /*{{{*/ 6653 6654 /*Declarations:{{{*/ 6655 int nel; 6656 IssmDouble planetarea,planetradius; 6657 IssmDouble constant,ratioe; 6658 IssmDouble rho_earth; 6659 IssmDouble lati,longi; 6660 IssmDouble latitude[NUMVERTICES]; 6661 IssmDouble longitude[NUMVERTICES]; 6662 IssmDouble x,y,z,dx,dy,dz,N_azim,E_azim; 6663 IssmDouble xyz_list[NUMVERTICES][3]; 6664 6665 #ifdef _HAVE_RESTRICT_ 6666 int** __restrict__ AlphaIndex=NULL; 6667 int** __restrict__ AzimIndex=NULL; 6668 6669 #else 6670 int** AlphaIndex=NULL; 6671 int** AzimIndex=NULL; 6672 #endif 6673 6674 /*viscoelastic green function:*/ 6675 int index; 6676 int M; 6677 IssmDouble doubleindex,lincoef, degacc; 6678 6679 /*Computational flags:*/ 6680 bool computeselfattraction = false; 6681 bool computeelastic = false; 6682 bool computeviscous = false; 6683 int horiz; 6684 int grd, grdmodel; 6685 6686 bool istime=true; 6687 IssmDouble timeacc=0; 6688 IssmDouble start_time,final_time; 6689 int nt,precomputednt; 6690 int intmax=pow(2,16)-1; 6691 6692 /*}}}*/ 6693 /*Recover parameters:{{{ */ 6694 rho_earth=FindParam(MaterialsEarthDensityEnum); 6695 this->parameters->FindParam(&computeselfattraction,SolidearthSettingsSelfAttractionEnum); 6696 this->parameters->FindParam(&computeelastic,SolidearthSettingsElasticEnum); 6697 this->parameters->FindParam(&computeviscous,SolidearthSettingsViscousEnum); 6698 this->parameters->FindParam(&nel,MeshNumberofelementsEnum); 6699 this->parameters->FindParam(&planetarea,SolidearthPlanetAreaEnum); 6700 this->parameters->FindParam(&planetradius,SolidearthPlanetRadiusEnum); 6701 this->parameters->FindParam(&horiz,SolidearthSettingsHorizEnum); 6702 this->parameters->FindParam(&grd,SolidearthSettingsGRDEnum); 6703 this->parameters->FindParam(&grdmodel,GrdModelEnum); 6704 /*}}}*/ 6705 6706 /*early return:*/ 6707 if (!grd || grdmodel!=ElasticEnum) return; //Love numbers won't be found in this case, return before loading them 6708 if(!computeselfattraction)return; 6709 6710 /*Recover precomputed green function kernels:{{{*/ 6711 parameters->FindParam(°acc,SolidearthSettingsDegreeAccuracyEnum); 6712 M=reCast<int,IssmDouble>(180.0/degacc+1.); 6713 6714 /*}}}*/ 6715 /*Compute lat long of all vertices in the element:{{{*/ 6716 ::GetVerticesCoordinates(&xyz_list[0][0],vertices,NUMVERTICES); 6717 for(int i=0;i<NUMVERTICES;i++){ 6718 latitude[i]= asin(xyz_list[i][2]/planetradius); 6719 longitude[i]= atan2(xyz_list[i][1],xyz_list[i][0]); 6720 } 6721 /*}}}*/ 6722 /*Compute green functions:{{{ */ 6723 6724 if(computeviscous){ 6725 this->parameters->FindParam(&istime,LoveIsTimeEnum); 6726 if(!istime)_error_("Frequency love numbers not supported yet!"); 6727 this->parameters->FindParam(&timeacc,SolidearthSettingsTimeAccEnum); 6728 this->parameters->FindParam(&start_time,TimesteppingStartTimeEnum); 6729 this->parameters->FindParam(&final_time,TimesteppingFinalTimeEnum); 6730 nt=reCast<int,IssmDouble>((final_time-start_time)/timeacc)+1; 6731 } 6732 else{ 6733 nt=1; //in elastic, or if we run only selfattraction, we need only one step 6734 } 6735 AlphaIndex=xNew<int*>(SLGEOM_NUMLOADS); 6736 if(horiz) AzimIndex=xNew<int*>(SLGEOM_NUMLOADS); 6737 6738 6739 //Allocate: 6740 for(int l=0;l<SLGEOM_NUMLOADS;l++){ 6741 int nbar=slgeom->nbar[l]; 6742 AlphaIndex[l]=xNewZeroInit<int>(3*nbar); 6743 if(horiz) AzimIndex[l]=xNewZeroInit<int>(3*nbar); 6744 6745 6746 for (int i=0;i<3;i++){ 6747 if(slgeom->lids[this->vertices[i]->lid]==this->lid){ 6748 for(int e=0;e<nbar;e++){ 6749 IssmDouble alpha; 6750 IssmDouble delPhi,delLambda; 6751 /*recover info for this element and vertex:*/ 6752 IssmDouble late= slgeom->latbarycentre[l][e]; 6753 IssmDouble longe= slgeom->longbarycentre[l][e]; 6754 late=late/180*M_PI; 6755 longe=longe/180*M_PI; 6756 6757 lati=latitude[i]; 6758 longi=longitude[i]; 6759 6760 if(horiz){ 6761 /*Compute azimuths*/ 6762 dx=cos(lati)*sin(late)-sin(lati)*cos(late)*cos(longe-longi); 6763 dy=sin(longe-longi)*cos(late); 6764 //angle between horiz motion and North, remapped from a double on [0,2*pi] to a int [0,intmax] 6765 AzimIndex[l][i*nbar+e]=reCast<int,IssmDouble>(intmax*(atan2(dy,dx)/2/M_PI)); 6766 } 6767 6768 /*Compute alpha angle between centroid and current vertex and index into precomputed tables: */ 6769 delPhi=fabs(lati-late); delLambda=fabs(longi-longe); if (delLambda>M_PI)delLambda=2*M_PI-delLambda; 6770 alpha=2.*asin(sqrt(pow(sin(delPhi/2.0),2.0)+cos(lati)*cos(late)*pow(sin(delLambda/2.0),2.0))); 6771 doubleindex=alpha/M_PI*reCast<IssmDouble,int>(M-1); //maps 0<alpha<PI on [0:M-1] 6772 index=reCast<int,IssmDouble>(doubleindex); //truncates doubleindex to integer part 6773 6774 if ((doubleindex-index)>=0.5) index+=1; //nearest neighbour 6775 if (index==M-1){ //avoids out of bound case 6776 index-=1; 6777 lincoef=1; 6778 } 6779 AlphaIndex[l][i*nbar+e]=index; 6780 } 6781 } 6782 } 6783 } 6784 6785 /*Save all these arrayins for each element:*/ 6786 for (int l=0;l<SLGEOM_NUMLOADS;l++){ 6787 this->inputs->SetIntArrayInput(slgeom->AlphaIndexEnum(l),this->lid,AlphaIndex[l],slgeom->nbar[l]*3); 6788 if(horiz) this->inputs->SetIntArrayInput(slgeom->AzimuthIndexEnum(l),this->lid,AzimIndex[l],slgeom->nbar[l]*3); 6789 } 6790 /*}}}*/ 6791 /*Free memory:{{{*/ 6792 for (int l=0;l<SLGEOM_NUMLOADS;l++){ 6793 xDelete<int>(AlphaIndex[l]); 6794 if(horiz) xDelete<int>(AzimIndex[l]); 6795 } 6796 xDelete<int*>(AlphaIndex); 6797 if(horiz) xDelete<int*>(AzimIndex); 6798 6726 6799 /*}}}*/ 6727 6800 return; … … 6936 7009 } 6937 7010 /*}}}*/ 7011 void Tria::SealevelchangeBarystaticLoads(GrdLoads* loads, BarystaticContributions* barycontrib, SealevelGeometry* slgeom){ /*{{{*/ 7012 7013 int nel; 7014 7015 /*Inputs:*/ 7016 IssmDouble I[NUMVERTICES]; 7017 IssmDouble W[NUMVERTICES]; 7018 IssmDouble BP[NUMVERTICES]; 7019 IssmDouble* areae=NULL; 7020 7021 /*output: */ 7022 IssmDouble bslcice=0; 7023 IssmDouble bslchydro=0; 7024 IssmDouble bslcbp=0; 7025 IssmDouble BPavg=0; 7026 IssmDouble Iavg=0; 7027 IssmDouble Wavg=0; 7028 7029 /*ice properties: */ 7030 IssmDouble rho_ice,rho_water,rho_freshwater; 7031 7032 /*recover some parameters:*/ 7033 this->parameters->FindParam(&rho_ice,MaterialsRhoIceEnum); 7034 this->parameters->FindParam(&rho_water,MaterialsRhoSeawaterEnum); 7035 this->parameters->FindParam(&rho_freshwater,MaterialsRhoFreshwaterEnum); 7036 this->parameters->FindParam(&areae,&nel,AreaeEnum); 7037 7038 /*Retrieve inputs:*/ 7039 Element::GetInputListOnVertices(&I[0],DeltaIceThicknessEnum); 7040 Element::GetInputListOnVertices(&W[0],DeltaTwsEnum); 7041 Element::GetInputListOnVertices(&BP[0],DeltaBottomPressureEnum); 7042 7043 for(int i=0;i<NUMVERTICES;i++){ 7044 Iavg+=I[i]*slgeom->LoadWeigths[SLGEOM_ICE][i][this->lid]*slgeom->LoadArea[SLGEOM_ICE][this->lid]; 7045 Wavg+=W[i]*slgeom->LoadWeigths[SLGEOM_WATER][i][this->lid]*slgeom->LoadArea[SLGEOM_WATER][this->lid]; 7046 BPavg+=BP[i]*slgeom->LoadWeigths[SLGEOM_OCEAN][i][this->lid]*slgeom->LoadArea[SLGEOM_OCEAN][this->lid]; 7047 } 7048 7049 /*convert from m^3 to kg:*/ 7050 Iavg*=rho_ice; 7051 Wavg*=rho_freshwater; 7052 BPavg*=rho_water; 7053 7054 #ifdef _ISSM_DEBUG_ 7055 this->AddInput(SealevelBarystaticIceLoadEnum,&Iavg,P0Enum); 7056 this->AddInput(SealevelBarystaticHydroLoadEnum,&Wavg,P0Enum); 7057 this->AddInput(SealevelBarystaticBpLoadEnum,&BPavg,P0Enum); 7058 #endif 7059 7060 /*Compute barystatic component in kg:*/ 7061 // Note: Iavg, etc, already include partial area factor phi for subelement loading 7062 bslcice = -Iavg; 7063 bslchydro = -Wavg; 7064 bslcbp = -BPavg; 7065 7066 _assert_(!xIsNan<IssmDouble>(bslcice)); 7067 _assert_(!xIsNan<IssmDouble>(bslchydro)); 7068 _assert_(!xIsNan<IssmDouble>(bslcbp)); 7069 7070 /*Plug values into subelement load vector:*/ 7071 if(slgeom->issubelement[SLGEOM_ICE][this->lid]){ 7072 int intj=slgeom->subelementmapping[SLGEOM_ICE][this->lid]; 7073 loads->vsubloads[SLGEOM_ICE]->SetValue(intj,Iavg,INS_VAL); 7074 Iavg=0; //avoid double counting centroid loads and subelement loads! 7075 } 7076 if(slgeom->issubelement[SLGEOM_WATER][this->lid]){ 7077 int intj=slgeom->subelementmapping[SLGEOM_WATER][this->lid]; 7078 loads->vsubloads[SLGEOM_WATER]->SetValue(intj,Wavg,INS_VAL); 7079 Wavg=0; 7080 } 7081 if(slgeom->issubelement[SLGEOM_OCEAN][this->lid]){ 7082 int intj=slgeom->subelementmapping[SLGEOM_OCEAN][this->lid]; 7083 loads->vsubloads[SLGEOM_OCEAN]->SetValue(intj,BPavg,INS_VAL); 7084 BPavg=0; 7085 } 7086 /*Plug remaining values into centroid load vector:*/ 7087 loads->vloads->SetValue(this->sid,Iavg+Wavg+BPavg,INS_VAL); 7088 7089 /*Keep track of barystatic contributions:*/ 7090 barycontrib->Set(this->Sid(),bslcice,bslchydro,bslcbp); 7091 7092 /*Free ressources*/ 7093 xDelete<IssmDouble>(areae); 7094 7095 }/*}}}*/ 6938 7096 void Tria::SealevelchangeGeometrySubElementLoads(SealevelGeometry* slgeom, IssmDouble* areae){ /*{{{*/ 6939 7097 … … 7036 7194 } 7037 7195 /*}}}*/ 7038 void Tria::SealevelchangeGeometrySubElementKernel(SealevelGeometry* slgeom){ /*{{{*/7039 7040 /*Declarations:{{{*/7041 int nel;7042 IssmDouble planetarea,planetradius;7043 IssmDouble constant,ratioe;7044 IssmDouble rho_earth;7045 IssmDouble lati,longi;7046 IssmDouble latitude[NUMVERTICES];7047 IssmDouble longitude[NUMVERTICES];7048 IssmDouble x,y,z,dx,dy,dz,N_azim,E_azim;7049 IssmDouble xyz_list[NUMVERTICES][3];7050 7051 #ifdef _HAVE_RESTRICT_7052 IssmDouble* __restrict__ G_viscoelastic_precomputed=NULL;7053 IssmDouble* __restrict__ G_gravi_precomputed=NULL;7054 IssmDouble* __restrict__ U_viscoelastic_precomputed=NULL;7055 IssmDouble* __restrict__ H_viscoelastic_precomputed=NULL;7056 IssmDouble** __restrict__ Gsubel=NULL;7057 IssmDouble** __restrict__ GUsubel=NULL;7058 IssmDouble** __restrict__ GNsubel=NULL;7059 IssmDouble** __restrict__ GEsubel=NULL;7060 7061 #else7062 IssmDouble* G_viscoelastic_precomputed=NULL;7063 IssmDouble* G_gravi_precomputed=NULL;7064 IssmDouble* U_viscoelastic_precomputed=NULL;7065 IssmDouble* H_viscoelastic_precomputed=NULL;7066 IssmDouble** Gsubel=NULL;7067 IssmDouble** GUsubel=NULL;7068 IssmDouble** GNsubel=NULL;7069 IssmDouble** GEsubel=NULL;7070 #endif7071 7072 /*viscoelastic green function:*/7073 int index;7074 int M;7075 IssmDouble doubleindex,lincoef;7076 7077 /*Computational flags:*/7078 bool computeselfattraction = false;7079 bool computeelastic = false;7080 bool computeviscous = false;7081 int horiz;7082 int grd, grdmodel;7083 7084 bool istime=true;7085 IssmDouble timeacc=0;7086 IssmDouble start_time,final_time;7087 int nt,precomputednt;7088 7089 /*}}}*/7090 /*Recover parameters:{{{ */7091 rho_earth=FindParam(MaterialsEarthDensityEnum);7092 this->parameters->FindParam(&computeselfattraction,SolidearthSettingsSelfAttractionEnum);7093 this->parameters->FindParam(&computeelastic,SolidearthSettingsElasticEnum);7094 this->parameters->FindParam(&computeviscous,SolidearthSettingsViscousEnum);7095 this->parameters->FindParam(&nel,MeshNumberofelementsEnum);7096 this->parameters->FindParam(&planetarea,SolidearthPlanetAreaEnum);7097 this->parameters->FindParam(&planetradius,SolidearthPlanetRadiusEnum);7098 this->parameters->FindParam(&horiz,SolidearthSettingsHorizEnum);7099 this->parameters->FindParam(&grd,SolidearthSettingsGRDEnum);7100 this->parameters->FindParam(&grdmodel,GrdModelEnum);7101 /*}}}*/7102 7103 /*early return:*/7104 if (!grd || grdmodel!=ElasticEnum) return; //Love numbers won't be found in this case, return before loading them7105 if(!computeselfattraction)return;7106 7107 /*Recover precomputed green function kernels:{{{*/7108 DoubleVecParam* parameter = static_cast<DoubleVecParam*>(this->parameters->FindParamObject(SealevelchangeGSelfAttractionEnum)); _assert_(parameter);7109 parameter->GetParameterValueByPointer((IssmDouble**)&G_gravi_precomputed,&M);7110 7111 if(computeelastic){7112 parameter = static_cast<DoubleVecParam*>(this->parameters->FindParamObject(SealevelchangeGViscoElasticEnum)); _assert_(parameter);7113 parameter->GetParameterValueByPointer((IssmDouble**)&G_viscoelastic_precomputed,NULL);7114 7115 parameter = static_cast<DoubleVecParam*>(this->parameters->FindParamObject(SealevelchangeUViscoElasticEnum)); _assert_(parameter);7116 parameter->GetParameterValueByPointer((IssmDouble**)&U_viscoelastic_precomputed,NULL);7117 7118 if(horiz){7119 parameter = static_cast<DoubleVecParam*>(this->parameters->FindParamObject(SealevelchangeHViscoElasticEnum)); _assert_(parameter);7120 parameter->GetParameterValueByPointer((IssmDouble**)&H_viscoelastic_precomputed,NULL);7121 7122 }7123 }7124 /*}}}*/7125 /*Compute lat long of all vertices in the element:{{{*/7126 ::GetVerticesCoordinates(&xyz_list[0][0],vertices,NUMVERTICES);7127 for(int i=0;i<NUMVERTICES;i++){7128 latitude[i]= asin(xyz_list[i][2]/planetradius);7129 longitude[i]= atan2(xyz_list[i][1],xyz_list[i][0]);7130 }7131 /*}}}*/7132 /*Compute green functions:{{{ */7133 constant=3/rho_earth/planetarea;7134 7135 if(computeviscous){7136 this->parameters->FindParam(&istime,LoveIsTimeEnum);7137 if(!istime)_error_("Frequency love numbers not supported yet!");7138 this->parameters->FindParam(&timeacc,SolidearthSettingsTimeAccEnum);7139 this->parameters->FindParam(&start_time,TimesteppingStartTimeEnum);7140 this->parameters->FindParam(&final_time,TimesteppingFinalTimeEnum);7141 nt=reCast<int,IssmDouble>((final_time-start_time)/timeacc)+1;7142 }7143 else{7144 nt=1; //in elastic, or if we run only selfattraction, we need only one step7145 }7146 Gsubel=xNew<IssmDouble*>(SLGEOM_NUMLOADS);7147 if(computeelastic){7148 GUsubel=xNew<IssmDouble*>(SLGEOM_NUMLOADS);7149 if(horiz){7150 GNsubel=xNew<IssmDouble*>(SLGEOM_NUMLOADS);7151 GEsubel=xNew<IssmDouble*>(SLGEOM_NUMLOADS);7152 }7153 }7154 7155 //Allocate:7156 for(int l=0;l<SLGEOM_NUMLOADS;l++){7157 int nbar=slgeom->nbar[l];7158 Gsubel[l]=xNewZeroInit<IssmDouble>(3*nbar*nt);7159 if(computeelastic){7160 GUsubel[l]=xNewZeroInit<IssmDouble>(3*nbar*nt);7161 if(horiz){7162 GNsubel[l]=xNewZeroInit<IssmDouble>(3*nbar*nt);7163 GEsubel[l]=xNewZeroInit<IssmDouble>(3*nbar*nt);7164 }7165 }7166 7167 for(int e=0;e<nbar;e++){7168 ratioe=constant*slgeom->area_subel[l][e];7169 for (int i=0;i<3;i++){7170 IssmDouble alpha;7171 IssmDouble delPhi,delLambda;7172 /*recover info for this element and vertex:*/7173 IssmDouble late= slgeom->latbarycentre[l][e];7174 IssmDouble longe= slgeom->longbarycentre[l][e];7175 late=late/180*M_PI;7176 longe=longe/180*M_PI;7177 7178 lati=latitude[i];7179 longi=longitude[i];7180 7181 if(horiz){7182 /*Compute azimuths, both north and east components: */7183 x = xyz_list[i][0]; y = xyz_list[i][1]; z = xyz_list[i][2];7184 if(lati==90){7185 x=1e-12; y=1e-12;7186 }7187 if(lati==-90){7188 x=1e-12; y=1e-12;7189 }7190 IssmDouble xbar=planetradius*cos(late)*cos(longe);7191 IssmDouble ybar=planetradius*cos(late)*sin(longe);7192 IssmDouble zbar=planetradius*sin(late);7193 7194 dx = xbar-x; dy = ybar-y; dz = zbar-z;7195 N_azim = (-z*x*dx-z*y*dy+(pow(x,2)+pow(y,2))*dz) /pow((pow(x,2)+pow(y,2))*(pow(x,2)+pow(y,2)+pow(z,2))*(pow(dx,2)+pow(dy,2)+pow(dz,2)),0.5);7196 E_azim = (-y*dx+x*dy) /pow((pow(x,2)+pow(y,2))*(pow(dx,2)+pow(dy,2)+pow(dz,2)),0.5);7197 }7198 7199 /*Compute alpha angle between centroid and current vertex and index into precomputed tables: */7200 delPhi=fabs(lati-late); delLambda=fabs(longi-longe); if (delLambda>M_PI)delLambda=2*M_PI-delLambda;7201 alpha=2.*asin(sqrt(pow(sin(delPhi/2.0),2.0)+cos(lati)*cos(late)*pow(sin(delLambda/2.0),2.0)));7202 doubleindex=alpha/M_PI*reCast<IssmDouble,int>(M-1); //maps 0<alpha<PI on [0:M-1]7203 index=reCast<int,IssmDouble>(doubleindex); //truncates doubleindex to integer part7204 7205 lincoef=doubleindex-index; //where between index and index+1 is alpha7206 if (index==M-1){ //avoids out of bound case7207 index-=1;7208 lincoef=1;7209 }7210 7211 for(int t=0;t<nt;t++){7212 int timeindex=i*nbar*nt+e*nt+t;7213 7214 /*Rigid earth gravitational perturbation: */7215 Gsubel[l][timeindex]+=G_gravi_precomputed[index+0]*(1.-lincoef)7216 +G_gravi_precomputed[index+1]*lincoef; //linear interpolation7217 7218 if(computeelastic){7219 Gsubel[l][timeindex]+=G_viscoelastic_precomputed[(index+0)*nt+t]*(1.-lincoef)7220 +G_viscoelastic_precomputed[(index+1)*nt+t]*lincoef; //linear interpolation7221 }7222 Gsubel[l][timeindex]*=ratioe;7223 7224 /*Elastic components:*/7225 if(computeelastic){7226 GUsubel[l][timeindex] = ratioe *(U_viscoelastic_precomputed[(index+0)*nt+t]*(1.-lincoef)7227 +U_viscoelastic_precomputed[(index+1)*nt+t]*lincoef);7228 if(horiz){7229 GNsubel[l][timeindex] = N_azim*ratioe *(H_viscoelastic_precomputed[(index+0)*nt+t]*(1.-lincoef)7230 +H_viscoelastic_precomputed[(index+1)*nt+t]*lincoef);7231 GEsubel[l][timeindex] = E_azim*ratioe *(H_viscoelastic_precomputed[(index+0)*nt+t]*(1.-lincoef)7232 +H_viscoelastic_precomputed[(index+1)*nt+t]*lincoef);7233 }7234 }7235 }7236 }7237 }7238 }7239 7240 /*Save all these arrayins for each element:*/7241 for (int l=0;l<SLGEOM_NUMLOADS;l++){7242 this->inputs->SetArrayInput(slgeom->GEnum(l),this->lid,Gsubel[l],slgeom->nbar[l]*3*nt);7243 if(computeelastic){7244 this->inputs->SetArrayInput(slgeom->GUEnum(l),this->lid,GUsubel[l],slgeom->nbar[l]*3*nt);7245 if(horiz){7246 this->inputs->SetArrayInput(slgeom->GNEnum(l),this->lid,GNsubel[l],slgeom->nbar[l]*3*nt);7247 this->inputs->SetArrayInput(slgeom->GEEnum(l),this->lid,GEsubel[l],slgeom->nbar[l]*3*nt);7248 }7249 }7250 }7251 /*}}}*/7252 /*Free memory:{{{*/7253 for (int l=0;l<SLGEOM_NUMLOADS;l++){7254 xDelete<IssmDouble>(Gsubel[l]);7255 if(computeelastic){7256 xDelete<IssmDouble>(GUsubel[l]);7257 if(horiz){7258 xDelete<IssmDouble>(GNsubel[l]);7259 xDelete<IssmDouble>(GEsubel[l]);7260 }7261 }7262 }7263 xDelete<IssmDouble*>(Gsubel);7264 if(computeelastic){7265 xDelete<IssmDouble*>(GUsubel);7266 if(horiz){7267 xDelete<IssmDouble*>(GNsubel);7268 xDelete<IssmDouble*>(GEsubel);7269 }7270 }7271 /*}}}*/7272 return;7273 7274 }7275 /*}}}*/7276 7196 void Tria::SealevelchangeUpdateViscousFields(IssmDouble lincoeff, int newindex, int offset){ /*{{{*/ 7277 7197 … … 7282 7202 IssmDouble* viscousE=NULL; 7283 7203 int viscousnumsteps; 7284 int dummy;7204 int size; 7285 7205 bool viscous=false; 7286 7206 int horiz=0; … … 7292 7212 this->parameters->FindParam(&viscousnumsteps,SealevelchangeViscousNumStepsEnum); 7293 7213 7294 this->inputs->GetArrayPtr(SealevelchangeViscousRSLEnum,this->lid,&viscousRSL,& dummy);7295 this->inputs->GetArrayPtr(SealevelchangeViscousUEnum,this->lid,&viscousU,& dummy);7214 this->inputs->GetArrayPtr(SealevelchangeViscousRSLEnum,this->lid,&viscousRSL,&size); 7215 this->inputs->GetArrayPtr(SealevelchangeViscousUEnum,this->lid,&viscousU,&size); 7296 7216 if(horiz){ 7297 this->inputs->GetArrayPtr(SealevelchangeViscousNEnum,this->lid,&viscousN,& dummy);7298 this->inputs->GetArrayPtr(SealevelchangeViscousEEnum,this->lid,&viscousE,& dummy);7217 this->inputs->GetArrayPtr(SealevelchangeViscousNEnum,this->lid,&viscousN,&size); 7218 this->inputs->GetArrayPtr(SealevelchangeViscousEEnum,this->lid,&viscousE,&size); 7299 7219 } 7300 7220 … … 7307 7227 } 7308 7228 } 7309 7310 } 7311 7312 } 7313 /*}}}*/ 7314 void Tria::SealevelchangeBarystaticLoads(GrdLoads* loads, BarystaticContributions* barycontrib, SealevelGeometry* slgeom){ /*{{{*/ 7315 7316 int nel; 7317 7318 /*Inputs:*/ 7319 IssmDouble I[NUMVERTICES]; 7320 IssmDouble W[NUMVERTICES]; 7321 IssmDouble BP[NUMVERTICES]; 7322 IssmDouble* areae=NULL; 7323 7324 /*output: */ 7325 IssmDouble bslcice=0; 7326 IssmDouble bslchydro=0; 7327 IssmDouble bslcbp=0; 7328 IssmDouble BPavg=0; 7329 IssmDouble Iavg=0; 7330 IssmDouble Wavg=0; 7331 7332 /*ice properties: */ 7333 IssmDouble rho_ice,rho_water,rho_freshwater; 7334 7335 /*recover some parameters:*/ 7336 this->parameters->FindParam(&rho_ice,MaterialsRhoIceEnum); 7229 } 7230 } 7231 /*}}}*/ 7232 void Tria::SealevelchangeOceanAverage(GrdLoads* loads, Vector<IssmDouble>* oceanareas, Vector<IssmDouble>* subelementoceanareas, IssmDouble* sealevelpercpu, SealevelGeometry* slgeom){ /*{{{*/ 7233 7234 IssmDouble oceanaverage=0; 7235 IssmDouble oceanarea=0; 7236 IssmDouble rho_water; 7237 7337 7238 this->parameters->FindParam(&rho_water,MaterialsRhoSeawaterEnum); 7338 this->parameters->FindParam(&rho_freshwater,MaterialsRhoFreshwaterEnum); 7339 this->parameters->FindParam(&areae,&nel,AreaeEnum); 7340 7341 /*Retrieve inputs:*/ 7342 Element::GetInputListOnVertices(&I[0],DeltaIceThicknessEnum); 7343 Element::GetInputListOnVertices(&W[0],DeltaTwsEnum); 7344 Element::GetInputListOnVertices(&BP[0],DeltaBottomPressureEnum); 7345 7239 7240 /*retrieve ocean average and area:*/ 7346 7241 for(int i=0;i<NUMVERTICES;i++){ 7347 Iavg+=I[i]*slgeom->LoadWeigths[SLGEOM_ICE][i][this->lid]; 7348 Wavg+=W[i]*slgeom->LoadWeigths[SLGEOM_WATER][i][this->lid]; 7349 BPavg+=BP[i]*slgeom->LoadWeigths[SLGEOM_OCEAN][i][this->lid]; 7350 } 7351 7352 /*convert from m to kg/m^2:*/ 7353 Iavg*=rho_ice; 7354 Wavg*=rho_freshwater; 7355 BPavg*=rho_water; 7356 7242 oceanaverage+=sealevelpercpu[this->vertices[i]->lid]*slgeom->LoadWeigths[SLGEOM_OCEAN][i][this->lid]; 7243 } 7357 7244 #ifdef _ISSM_DEBUG_ 7358 this->AddInput(SealevelBarystaticIceLoadEnum,&Iavg,P0Enum); 7359 this->AddInput(SealevelBarystaticHydroLoadEnum,&Wavg,P0Enum); 7360 this->AddInput(SealevelBarystaticBpLoadEnum,&BPavg,P0Enum); 7245 this->AddInput(SealevelBarystaticOceanLoadEnum,&oceanaverage,P0Enum); 7361 7246 #endif 7362 7363 /*Compute barystatic component in kg:*/ 7364 // Note: Iavg, etc, already include partial area factor phi for subelement loading 7365 bslcice = -slgeom->LoadArea[SLGEOM_ICE][this->lid]*Iavg; 7366 bslchydro = -slgeom->LoadArea[SLGEOM_WATER][this->lid]*Wavg; 7367 bslcbp = -slgeom->LoadArea[SLGEOM_OCEAN][this->lid]*BPavg; 7368 7369 _assert_(!xIsNan<IssmDouble>(bslcice)); 7370 _assert_(!xIsNan<IssmDouble>(bslchydro)); 7371 _assert_(!xIsNan<IssmDouble>(bslcbp)); 7372 7373 /*Plug values into subelement load vector:*/ 7374 if(slgeom->issubelement[SLGEOM_ICE][this->lid]){ 7375 int intj=slgeom->subelementmapping[SLGEOM_ICE][this->lid]; 7376 loads->vsubloads[SLGEOM_ICE]->SetValue(intj,Iavg,INS_VAL); 7377 Iavg=0; //avoid double counting centroid loads and subelement loads! 7378 } 7379 if(slgeom->issubelement[SLGEOM_WATER][this->lid]){ 7380 int intj=slgeom->subelementmapping[SLGEOM_WATER][this->lid]; 7381 loads->vsubloads[SLGEOM_WATER]->SetValue(intj,Wavg,INS_VAL); 7382 Wavg=0; 7383 } 7247 oceanarea=slgeom->LoadArea[SLGEOM_OCEAN][this->lid]; 7248 7249 /*add ocean average in the global sealevelloads vector:*/ 7384 7250 if(slgeom->issubelement[SLGEOM_OCEAN][this->lid]){ 7385 7251 int intj=slgeom->subelementmapping[SLGEOM_OCEAN][this->lid]; 7386 loads->vsubloads[SLGEOM_OCEAN]->SetValue(intj,BPavg,INS_VAL); 7387 BPavg=0; 7388 } 7389 /*Plug remaining values into centroid load vector:*/ 7390 loads->vloads->SetValue(this->sid,Iavg+Wavg+BPavg,INS_VAL); 7391 7392 /*Keep track of barystatic contributions:*/ 7393 barycontrib->Set(this->Sid(),bslcice,bslchydro,bslcbp); 7394 7252 loads->vsubsealevelloads->SetValue(intj,oceanaverage*rho_water*oceanarea,INS_VAL); 7253 loads->vsealevelloads->SetValue(this->sid,0.,INS_VAL); 7254 } 7255 else loads->vsealevelloads->SetValue(this->sid,oceanaverage*rho_water*oceanarea,INS_VAL); 7256 7257 /*add ocean area into a global oceanareas vector:*/ 7258 if(!loads->sealevelloads){ 7259 oceanareas->SetValue(this->sid,oceanarea,INS_VAL); 7260 if(slgeom->issubelement[SLGEOM_OCEAN][this->lid]){ 7261 int intj=slgeom->subelementmapping[SLGEOM_OCEAN][this->lid]; 7262 subelementoceanareas->SetValue(intj,oceanarea,INS_VAL); 7263 } 7264 } 7395 7265 } 7396 7266 /*}}}*/ … … 7398 7268 7399 7269 /*sal green function:*/ 7270 int* AlphaIndex=NULL; 7271 int* AlphaIndexsub[SLGEOM_NUMLOADS]; 7400 7272 IssmDouble* G=NULL; 7401 7273 IssmDouble* Grot=NULL; 7402 IssmDouble* Gsub[SLGEOM_NUMLOADS];7274 DoubleVecParam* parameter; 7403 7275 bool computefuture=false; 7276 int spatial_component=0; 7404 7277 7405 7278 bool sal = false; … … 7417 7290 7418 7291 if(sal){ 7419 this->inputs->GetArrayPtr(SealevelchangeGEnum,this->lid,&G,&size); 7420 this->inputs->GetArrayPtr(SealevelchangeGsubelIceEnum,this->lid,&Gsub[SLGEOM_ICE],&size); 7421 this->inputs->GetArrayPtr(SealevelchangeGsubelHydroEnum,this->lid,&Gsub[SLGEOM_WATER],&size); 7422 this->inputs->GetArrayPtr(SealevelchangeGsubelOceanEnum,this->lid,&Gsub[SLGEOM_OCEAN],&size); 7292 parameter = static_cast<DoubleVecParam*>(this->parameters->FindParamObject(SealevelchangeGViscoElasticEnum)); _assert_(parameter); 7293 parameter->GetParameterValueByPointer((IssmDouble**)&G,NULL); 7294 7295 this->inputs->GetIntArrayPtr(SealevelchangeAlphaIndexEnum,this->lid,&AlphaIndex,&size); 7296 for (int l=0;l<SLGEOM_NUMLOADS;l++) this->inputs->GetIntArrayPtr(slgeom->AlphaIndexEnum(l),this->lid,&AlphaIndexsub[l],&size); 7423 7297 if (rotation) this->inputs->GetArrayPtr(SealevelchangeGrotEnum,this->lid,&Grot,&size); 7424 7298 7425 this->SealevelchangeGxL(sealevelpercpu, G, Gsub, Grot, loads, polarmotionvector, slgeom, nel,percpu=true,SealevelchangeViscousRSLEnum,computefuture=false); 7426 } 7427 7428 return; 7429 } /*}}}*/ 7430 void Tria::SealevelchangeOceanAverage(GrdLoads* loads, Vector<IssmDouble>* oceanareas, Vector<IssmDouble>* subelementoceanareas, IssmDouble* sealevelpercpu, SealevelGeometry* slgeom){ /*{{{*/ 7431 7432 IssmDouble oceanaverage=0; 7433 IssmDouble oceanarea=0; 7434 IssmDouble rho_water; 7435 7436 this->parameters->FindParam(&rho_water,MaterialsRhoSeawaterEnum); 7437 7438 /*retrieve ocean average and area:*/ 7439 for(int i=0;i<NUMVERTICES;i++){ 7440 oceanaverage+=sealevelpercpu[this->vertices[i]->lid]*slgeom->LoadWeigths[SLGEOM_OCEAN][i][this->lid]; 7441 } 7442 #ifdef _ISSM_DEBUG_ 7443 this->AddInput(SealevelBarystaticOceanLoadEnum,&oceanaverage,P0Enum); 7444 #endif 7445 oceanarea=slgeom->LoadArea[SLGEOM_OCEAN][this->lid]; 7446 7447 /*add ocean average in the global sealevelloads vector:*/ 7448 if(slgeom->issubelement[SLGEOM_OCEAN][this->lid]){ 7449 int intj=slgeom->subelementmapping[SLGEOM_OCEAN][this->lid]; 7450 loads->vsubsealevelloads->SetValue(intj,oceanaverage*rho_water,INS_VAL); 7451 loads->vsealevelloads->SetValue(this->sid,0.,INS_VAL); 7452 } 7453 else loads->vsealevelloads->SetValue(this->sid,oceanaverage*rho_water,INS_VAL); 7454 7455 /*add ocean area into a global oceanareas vector:*/ 7456 if(!loads->sealevelloads){ 7457 oceanareas->SetValue(this->sid,oceanarea,INS_VAL); 7458 if(slgeom->issubelement[SLGEOM_OCEAN][this->lid]){ 7459 int intj=slgeom->subelementmapping[SLGEOM_OCEAN][this->lid]; 7460 subelementoceanareas->SetValue(intj,oceanarea,INS_VAL); 7461 } 7299 this->SealevelchangeGxL(sealevelpercpu, spatial_component=0,AlphaIndex, AlphaIndexsub, NULL, NULL, G, Grot, loads, polarmotionvector, slgeom, nel,percpu=true,SealevelchangeViscousRSLEnum,computefuture=false); 7462 7300 } 7463 7301 … … 7473 7311 int nel,nbar; 7474 7312 bool sal = false; 7313 int* AlphaIndex=NULL; 7314 int* AzimIndex=NULL; 7315 int* AlphaIndexsub[SLGEOM_NUMLOADS]; 7316 int* AzimIndexsub[SLGEOM_NUMLOADS]; 7317 int spatial_component=0; 7475 7318 IssmDouble* G=NULL; 7476 7319 IssmDouble* GU=NULL; 7477 IssmDouble* GE=NULL; 7478 IssmDouble* GN=NULL; 7320 IssmDouble* GH=NULL; 7479 7321 IssmDouble* Grot=NULL; 7480 7322 IssmDouble* GUrot=NULL; 7481 7323 IssmDouble* GNrot=NULL; 7482 7324 IssmDouble* GErot=NULL; 7483 IssmDouble* Gsub[SLGEOM_NUMLOADS]; 7484 IssmDouble* GUsub[SLGEOM_NUMLOADS]; 7485 IssmDouble* GNsub[SLGEOM_NUMLOADS]; 7486 IssmDouble* GEsub[SLGEOM_NUMLOADS]; 7325 7326 DoubleVecParam* parameter; 7487 7327 bool computefuture=false; 7488 7328 … … 7503 7343 7504 7344 if(sal){ 7505 7506 this->inputs->GetArrayPtr(SealevelchangeGEnum,this->lid,&G,&size);7507 this->inputs->GetArrayPtr(SealevelchangeGsubelIceEnum,this->lid,&Gsub[SLGEOM_ICE],&size); 7508 this->inputs->GetArrayPtr(SealevelchangeGsubelHydroEnum,this->lid,&Gsub[SLGEOM_WATER],&size);7509 this->inputs->GetArrayPtr(SealevelchangeGsubelOceanEnum,this->lid,&Gsub[SLGEOM_OCEAN],&size);7345 this->inputs->GetIntArrayPtr(SealevelchangeAlphaIndexEnum,this->lid,&AlphaIndex,&size); 7346 for (int l=0;l<SLGEOM_NUMLOADS;l++) this->inputs->GetIntArrayPtr(slgeom->AlphaIndexEnum(l),this->lid,&AlphaIndexsub[l],&size); 7347 7348 parameter = static_cast<DoubleVecParam*>(this->parameters->FindParamObject(SealevelchangeGViscoElasticEnum)); _assert_(parameter); 7349 parameter->GetParameterValueByPointer((IssmDouble**)&G,NULL); 7510 7350 7511 7351 if(elastic){ 7512 this->inputs->GetArrayPtr(SealevelchangeGUEnum,this->lid,&GU,&size); 7513 this->inputs->GetArrayPtr(SealevelchangeGUsubelIceEnum,this->lid,&GUsub[SLGEOM_ICE],&size); 7514 this->inputs->GetArrayPtr(SealevelchangeGUsubelHydroEnum,this->lid,&GUsub[SLGEOM_WATER],&size); 7515 this->inputs->GetArrayPtr(SealevelchangeGUsubelOceanEnum,this->lid,&GUsub[SLGEOM_OCEAN],&size); 7352 parameter = static_cast<DoubleVecParam*>(this->parameters->FindParamObject(SealevelchangeUViscoElasticEnum)); _assert_(parameter); 7353 parameter->GetParameterValueByPointer((IssmDouble**)&GU,NULL); 7354 7516 7355 if(horiz){ 7517 this->inputs->GetArrayPtr(SealevelchangeGNEnum,this->lid,&GN,&size); 7518 this->inputs->GetArrayPtr(SealevelchangeGNsubelIceEnum,this->lid,&GNsub[SLGEOM_ICE],&size); 7519 this->inputs->GetArrayPtr(SealevelchangeGNsubelHydroEnum,this->lid,&GNsub[SLGEOM_WATER],&size); 7520 this->inputs->GetArrayPtr(SealevelchangeGNsubelOceanEnum,this->lid,&GNsub[SLGEOM_OCEAN],&size); 7521 7522 this->inputs->GetArrayPtr(SealevelchangeGEEnum,this->lid,&GE,&size); 7523 this->inputs->GetArrayPtr(SealevelchangeGEsubelIceEnum,this->lid,&GEsub[SLGEOM_ICE],&size); 7524 this->inputs->GetArrayPtr(SealevelchangeGEsubelHydroEnum,this->lid,&GEsub[SLGEOM_WATER],&size); 7525 this->inputs->GetArrayPtr(SealevelchangeGEsubelOceanEnum,this->lid,&GEsub[SLGEOM_OCEAN],&size); 7356 this->inputs->GetIntArrayPtr(SealevelchangeAzimuthIndexEnum,this->lid,&AzimIndex,&size); 7357 for (int l=0;l<SLGEOM_NUMLOADS;l++) this->inputs->GetIntArrayPtr(slgeom->AzimuthIndexEnum(l),this->lid,&AzimIndexsub[l],&size); 7358 7359 parameter = static_cast<DoubleVecParam*>(this->parameters->FindParamObject(SealevelchangeHViscoElasticEnum)); _assert_(parameter); 7360 parameter->GetParameterValueByPointer((IssmDouble**)&GH,NULL); 7526 7361 } 7527 7362 if (rotation) { … … 7534 7369 } 7535 7370 } 7536 this->SealevelchangeGxL(&RSLGrd[0],G, Gsub, Grot, loads, polarmotionvector, slgeom, nel,percpu=false,SealevelchangeViscousRSLEnum,computefuture=true); 7371 7372 this->SealevelchangeGxL(&RSLGrd[0],spatial_component=0, AlphaIndex, AlphaIndexsub,NULL, NULL,G, Grot, loads, polarmotionvector, slgeom, nel,percpu=false,SealevelchangeViscousRSLEnum,computefuture=true); 7537 7373 7538 7374 if(elastic){ 7539 this->SealevelchangeGxL(&UGrd[0], GU, GUsub, GUrot, loads, polarmotionvector, slgeom, nel,percpu=false,SealevelchangeViscousUEnum,computefuture=true);7375 this->SealevelchangeGxL(&UGrd[0],spatial_component=0, AlphaIndex, AlphaIndexsub,NULL, NULL, GU, GUrot, loads, polarmotionvector, slgeom, nel,percpu=false,SealevelchangeViscousUEnum,computefuture=true); 7540 7376 if(horiz){ 7541 this->SealevelchangeGxL(&NGrd[0], GN, GNsub, GNrot, loads, polarmotionvector, slgeom, nel,percpu=false,SealevelchangeViscousNEnum,computefuture=true);7542 this->SealevelchangeGxL(&EGrd[0], GE, GEsub, GErot, loads, polarmotionvector, slgeom, nel,percpu=false,SealevelchangeViscousEEnum,computefuture=true);7377 this->SealevelchangeGxL(&NGrd[0],spatial_component=1,AlphaIndex, AlphaIndexsub,AzimIndex,AzimIndexsub,GH, GNrot, loads, polarmotionvector, slgeom, nel,percpu=false,SealevelchangeViscousNEnum,computefuture=true); 7378 this->SealevelchangeGxL(&EGrd[0],spatial_component=2,AlphaIndex, AlphaIndexsub,AzimIndex,AzimIndexsub,GH, GErot, loads, polarmotionvector, slgeom, nel,percpu=false,SealevelchangeViscousEEnum,computefuture=true); 7543 7379 } 7544 7380 } … … 7565 7401 7566 7402 } /*}}}*/ 7567 void Tria::SealevelchangeGxL(IssmDouble* grdfieldout, IssmDouble* G, IssmDouble** Gsub, IssmDouble* Grot, GrdLoads* loads, IssmDouble* polarmotionvector, SealevelGeometry* slgeom, int nel, bool percpu, int viscousenum, bool computefuture) { /*{{{*/7403 void Tria::SealevelchangeGxL(IssmDouble* grdfieldout, int spatial_component, int* AlphaIndex, int** AlphaIndexsub, int* AzimIndex, int**AzimIndexsub, IssmDouble* G, IssmDouble* Grot, GrdLoads* loads, IssmDouble* polarmotionvector, SealevelGeometry* slgeom, int nel, bool percpu, int viscousenum, bool computefuture) { /*{{{*/ 7568 7404 7569 7405 //This function performs the actual convolution between Green functions and surface Loads for a particular grd field 7570 7406 7571 7407 IssmDouble* grdfield=NULL; 7572 int i,e,l,t,nbar; 7408 int i,e,l,t,a, index, nbar; 7409 bool rotation=false; 7410 IssmDouble* Centroid_loads=NULL; 7411 IssmDouble* Centroid_loads_copy=NULL; 7412 IssmDouble* Subelement_loads[SLGEOM_NUMLOADS]; 7413 IssmDouble* Subelement_loads_copy[SLGEOM_NUMLOADS]; 7414 IssmDouble* horiz_projection=NULL; 7415 IssmDouble* horiz_projectionsub[SLGEOM_NUMLOADS]; 7416 int nt=1; //important, ensures there is a defined value if computeviscous is false 7417 7418 //viscous 7573 7419 bool computeviscous=false; 7574 bool rotation=false;7575 IssmDouble* viscousfield=NULL;7576 int nt=1; //important, ensures there is a defined value if computeviscous is false7577 7420 int viscousindex=0; //important 7578 7421 int viscousnumsteps=1; //important 7422 IssmDouble* viscousfield=NULL; 7423 IssmDouble* grdfieldinterp=NULL; 7424 IssmDouble* viscoustimes=NULL; 7425 IssmDouble final_time; 7426 IssmDouble lincoeff; 7427 IssmDouble timeacc; 7579 7428 7580 7429 this->parameters->FindParam(&computeviscous,SolidearthSettingsViscousEnum); … … 7583 7432 this->parameters->FindParam(&viscousnumsteps,SealevelchangeViscousNumStepsEnum); 7584 7433 this->parameters->FindParam(&viscousindex,SealevelchangeViscousIndexEnum); 7434 this->parameters->FindParam(&viscoustimes,NULL,SealevelchangeViscousTimesEnum); 7435 this->parameters->FindParam(&final_time,TimesteppingFinalTimeEnum); 7436 this->parameters->FindParam(&timeacc,SolidearthSettingsTimeAccEnum); 7437 this->inputs->GetArrayPtr(viscousenum,this->lid,&viscousfield,NULL); 7585 7438 if(computefuture) { 7586 7439 nt=viscousnumsteps-viscousindex+2; //number of time steps remaining to reach final_time, +1 is sufficient with no adaptative time stepping, +2 necessary otherwise; we assume the safe choice here for the sake of simplicity 7587 7440 if (nt>viscousnumsteps) nt=viscousnumsteps; 7441 grdfieldinterp=xNewZeroInit<IssmDouble>(3*viscousnumsteps); 7588 7442 } 7589 7443 else nt=1; … … 7605 7459 } 7606 7460 7607 7608 if(loads->sealevelloads){ // general case: loads + sealevel loads 7609 for(i=0;i<NUMVERTICES;i++) { 7610 if(slgeom->lids[this->vertices[i]->lid]!=this->lid)continue; 7611 for (e=0;e<nel;e++){ 7612 for(t=0;t<nt;t++){ 7613 int index=i*nel*viscousnumsteps+e*viscousnumsteps+t; 7614 grdfield[i*nt+t]+=G[index]*(loads->sealevelloads[e]+loads->loads[e]); 7461 //Determine loads /*{{{*/ 7462 Centroid_loads=xNewZeroInit<IssmDouble>(nel); 7463 for (e=0;e<nel;e++){ 7464 Centroid_loads[e]=loads->loads[e]; 7465 } 7466 for(l=0;l<SLGEOM_NUMLOADS;l++){ 7467 nbar=slgeom->nbar[l]; 7468 Subelement_loads[l]=xNewZeroInit<IssmDouble>(nbar); 7469 for (e=0;e<nbar;e++){ 7470 Subelement_loads[l][e]=(loads->subloads[l][e]); 7471 } 7472 } 7473 if(loads->sealevelloads){ 7474 for (e=0;e<nel;e++){ 7475 Centroid_loads[e]+=(loads->sealevelloads[e]); 7476 } 7477 nbar=slgeom->nbar[SLGEOM_OCEAN]; 7478 for (e=0;e<nbar;e++){ 7479 Subelement_loads[SLGEOM_OCEAN][e]+=(loads->subsealevelloads[e]); 7480 } 7481 } 7482 7483 //Copy loads if dealing with a horizontal component: the result will need to be projected against the North or East axis for each vertex 7484 if (spatial_component!=0){ 7485 horiz_projection=xNewZeroInit<IssmDouble>(3*nel); 7486 Centroid_loads_copy=xNewZeroInit<IssmDouble>(nel); 7487 for (e=0;e<nel;e++){ 7488 Centroid_loads_copy[e]=Centroid_loads[e]; 7489 } 7490 7491 for(l=0;l<SLGEOM_NUMLOADS;l++){ 7492 nbar=slgeom->nbar[l]; 7493 Subelement_loads_copy[l]=xNewZeroInit<IssmDouble>(nbar); 7494 horiz_projectionsub[l]=xNewZeroInit<IssmDouble>(3*nbar); 7495 for (e=0;e<nbar;e++){ 7496 Subelement_loads_copy[l][e]=Subelement_loads[l][e]; 7497 } 7498 } 7499 } 7500 /*}}}*/ 7501 7502 //Convolution 7503 for(i=0;i<NUMVERTICES;i++) { /*{{{*/ 7504 if(slgeom->lids[this->vertices[i]->lid]!=this->lid)continue; 7505 7506 if (spatial_component!=0){ //horizontals /*{{{*/ 7507 //GxL needs to be projected on the right axis before summation into the grd field 7508 //here we apply the projection scalar to the load prior to the actual convolution loop for more efficiency 7509 if (spatial_component==1){ //north 7510 for (e=0;e<nel;e++){ 7511 horiz_projection[i*nel+e]=cos(2.0*M_PI*reCast<IssmDouble,int>(AzimIndex[i*nel+e])/65535.0); // 65535=2^16-1 = max value of 16 bits unsigned int 7615 7512 } 7616 } 7513 for(l=0;l<SLGEOM_NUMLOADS;l++){ 7514 nbar=slgeom->nbar[l]; 7515 for (e=0;e<nbar;e++){ 7516 horiz_projectionsub[l][i*nbar+e]=cos(2.0*M_PI*reCast<IssmDouble,int>(AzimIndexsub[l][i*nbar+e])/65535.0);; 7517 } 7518 } 7519 } 7520 else if (spatial_component==2){ //east 7521 for (e=0;e<nel;e++){ 7522 horiz_projection[i*nel+e]=sin(2.0*M_PI*reCast<IssmDouble,int>(AzimIndex[i*nel+e])/65535.0); 7523 } 7524 for(l=0;l<SLGEOM_NUMLOADS;l++){ 7525 nbar=slgeom->nbar[l]; 7526 for (e=0;e<nbar;e++){ 7527 horiz_projectionsub[l][i*nbar+e]=sin(2.0*M_PI*reCast<IssmDouble,int>(AzimIndexsub[l][i*nbar+e])/65535.0);; 7528 } 7529 } 7530 } 7531 for (e=0;e<nel;e++) Centroid_loads[e]=Centroid_loads_copy[e]*horiz_projection[i*nel+e]; 7617 7532 for(l=0;l<SLGEOM_NUMLOADS;l++){ 7618 7533 nbar=slgeom->nbar[l]; 7619 7534 for (e=0;e<nbar;e++){ 7620 for(t=0;t<nt;t++){ 7621 int index=i*nbar*viscousnumsteps+e*viscousnumsteps+t; 7622 grdfield[i*nt+t]+=Gsub[l][index]*(loads->subloads[l][e]); 7623 } 7535 Subelement_loads[l][e]=Subelement_loads_copy[l][e]*horiz_projectionsub[l][i*nbar+e]; 7624 7536 } 7625 if(l==SLGEOM_OCEAN){ 7626 for (e=0;e<nbar;e++){ 7627 for(t=0;t<nt;t++){ 7628 int index=i*nbar*viscousnumsteps+e*viscousnumsteps+t; 7629 grdfield[i*nt+t]+=Gsub[l][index]*(loads->subsealevelloads[e]); 7630 } 7631 } 7537 } 7538 } /*}}}*/ 7539 7540 for (e=0;e<nel;e++){ 7541 for(t=0;t<nt;t++){ 7542 a=AlphaIndex[i*nel+e]; 7543 grdfield[i*nt+t]+=G[a*viscousnumsteps+t]*Centroid_loads[e]; 7544 } 7545 } 7546 for(l=0;l<SLGEOM_NUMLOADS;l++){ 7547 nbar=slgeom->nbar[l]; 7548 for (e=0;e<nbar;e++){ 7549 for(t=0;t<nt;t++){ 7550 a=AlphaIndexsub[l][i*nbar+e]; 7551 grdfield[i*nt+t]+=G[a*viscousnumsteps+t]*Subelement_loads[l][e]; 7632 7552 } 7633 7553 } 7634 7554 } 7635 } 7636 else{ //this is the initial convolution where only loads are provided 7637 for(i=0;i<NUMVERTICES;i++) { 7638 if(slgeom->lids[this->vertices[i]->lid]!=this->lid)continue; 7639 for (e=0;e<nel;e++){ 7640 for(t=0;t<nt;t++){ 7641 int index=i*nel*viscousnumsteps+e*viscousnumsteps+t; 7642 grdfield[i*nt+t]+=G[index]*(loads->loads[e]); 7643 } 7644 } 7645 for(l=0;l<SLGEOM_NUMLOADS;l++){ 7646 nbar=slgeom->nbar[l]; 7647 for (e=0;e<nbar;e++){ 7648 for(t=0;t<nt;t++){ 7649 int index=i*nbar*viscousnumsteps+e*viscousnumsteps+t; 7650 grdfield[i*nt+t]+=Gsub[l][index]*(loads->subloads[l][e]); 7651 } 7652 } 7653 } 7654 } 7655 } 7555 } /*}}}*/ 7556 7557 7656 7558 7657 7559 if(computeviscous){ /*{{{*/ … … 7661 7563 // 3*: subtract from viscous stack the grdfield that has already been accounted for so we don't add it again at the next time step 7662 7564 7663 IssmDouble* grdfieldinterp=NULL;7664 IssmDouble* viscoustimes=NULL;7665 IssmDouble final_time;7666 IssmDouble lincoeff;7667 IssmDouble timeacc;7668 7669 this->parameters->FindParam(&viscoustimes,NULL,SealevelchangeViscousTimesEnum);7670 this->parameters->FindParam(&final_time,TimesteppingFinalTimeEnum);7671 this->parameters->FindParam(&timeacc,SolidearthSettingsTimeAccEnum);7672 this->inputs->GetArrayPtr(viscousenum,this->lid,&viscousfield,NULL);7673 7565 /* Map new grdfield generated by present-day loads onto viscous time vector*/ 7674 7566 if(computefuture){ 7675 grdfieldinterp=xNewZeroInit<IssmDouble>(3*viscousnumsteps);7676 7567 //viscousindex time and first time step of grdfield coincide, so just copy that value 7677 7568 for(int i=0;i<NUMVERTICES;i++){ … … 7685 7576 for(int i=0;i<NUMVERTICES;i++){ 7686 7577 if(slgeom->lids[this->vertices[i]->lid]!=this->lid)continue; 7687 grdfieldinterp[i*viscousnumsteps+t]= (1-lincoeff)*grdfield[i*nt+(t-viscousindex-1)]+lincoeff*grdfield[i*nt+(t-viscousindex)]; 7578 grdfieldinterp[i*viscousnumsteps+t] = (1-lincoeff)*grdfield[i*nt+(t-viscousindex-1)] 7579 +lincoeff*grdfield[i*nt+(t-viscousindex)]; 7688 7580 } 7689 7581 } … … 7699 7591 /*update viscous stack with future deformation from present load: */ 7700 7592 if(computefuture){ 7701 for(int t=viscousnumsteps-1;t>=viscousindex;t--){ 7593 for(int t=viscousnumsteps-1;t>=viscousindex;t--){ //we need to go backwards so as not to zero out viscousfield[i*viscousnumsteps+viscousindex] until the end 7702 7594 for(int i=0;i<NUMVERTICES;i++){ 7703 7595 if(slgeom->lids[this->vertices[i]->lid]!=this->lid)continue; 7704 7596 //offset viscousfield to remove all deformation that has already been added 7705 viscousfield[i*viscousnumsteps+t]+=grdfieldinterp[i*viscousnumsteps+t]-grdfieldinterp[i*viscousnumsteps+viscousindex]-viscousfield[i*viscousnumsteps+viscousindex]; 7597 viscousfield[i*viscousnumsteps+t]+=grdfieldinterp[i*viscousnumsteps+t] 7598 -grdfieldinterp[i*viscousnumsteps+viscousindex] 7599 -viscousfield[i*viscousnumsteps+viscousindex]; 7706 7600 } 7707 7601 } 7708 7602 /*Save viscous stack now that we updated the values:*/ 7709 7603 this->inputs->SetArrayInput(viscousenum,this->lid,viscousfield,3*viscousnumsteps); 7710 } 7711 7712 /*Free allocatoins:*/7713 xDelete<IssmDouble>(viscoustimes);7604 7605 /*Free resources:*/ 7606 xDelete<IssmDouble>(grdfieldinterp); 7607 } 7714 7608 } 7715 7609 /*}}}*/ … … 7726 7620 for(i=0;i<NUMVERTICES;i++) grdfieldout[i]=grdfield[i*nt+0]; 7727 7621 } 7622 //free resources 7623 xDelete<IssmDouble>(grdfield); 7624 xDelete<IssmDouble>(Centroid_loads); 7625 for(l=0;l<SLGEOM_NUMLOADS;l++) xDelete<IssmDouble>(Subelement_loads[l]); 7626 if (spatial_component!=0){ 7627 xDelete<IssmDouble>(horiz_projection); 7628 xDelete<IssmDouble>(Centroid_loads_copy); 7629 for(l=0;l<SLGEOM_NUMLOADS;l++) { 7630 xDelete<IssmDouble>(Subelement_loads_copy[l]); 7631 xDelete<IssmDouble>(horiz_projectionsub[l]); 7632 } 7633 } 7634 if (computeviscous){ 7635 xDelete<IssmDouble>(viscoustimes); 7636 if (computefuture){ 7637 xDelete<IssmDouble>(grdfieldinterp); 7638 } 7639 } 7728 7640 7729 7641 } /*}}}*/ … … 7731 7643 void Tria::SealevelchangeShift(GrdLoads* loads, IssmDouble offset, SealevelGeometry* slgeom){ /*{{{*/ 7732 7644 7645 offset*=slgeom->LoadArea[SLGEOM_OCEAN][this->lid]; //kg.m^-2 to kg 7733 7646 if(slgeom->isoceanin[this->lid]){ 7734 7647 if(slgeom->issubelement[SLGEOM_OCEAN][this->lid]){
Note:
See TracChangeset
for help on using the changeset viewer.