Changeset 26242
- Timestamp:
- 05/05/21 15:40:27 (4 years ago)
- Location:
- issm/trunk-jpl
- Files:
-
- 13 edited
Legend:
- Unmodified
- Added
- Removed
-
issm/trunk-jpl/src/c/analyses/LoveAnalysis.cpp
r26234 r26242 42 42 parameters->AddObject(iomodel->CopyConstantObject("md.love.inner_core_boundary",LoveInnerCoreBoundaryEnum)); 43 43 parameters->AddObject(iomodel->CopyConstantObject("md.love.core_mantle_boundary",LoveCoreMantleBoundaryEnum)); 44 parameters->AddObject(iomodel->CopyConstantObject("md.love.complex_computation",LoveComplexComputationEnum)); 44 45 }/*}}}*/ 45 46 void LoveAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/ -
issm/trunk-jpl/src/c/analyses/SealevelchangeAnalysis.cpp
r26222 r26242 66 66 67 67 /*Initialize solid earth motion and sea level: */ 68 InputUpdateFromConstantx(inputs,elements,0.,BedEastEnum);69 InputUpdateFromConstantx(inputs,elements,0.,BedNorthEnum);68 iomodel->ConstantToInput(inputs,elements,0.,BedEastEnum,P1Enum); 69 iomodel->ConstantToInput(inputs,elements,0.,BedNorthEnum,P1Enum); 70 70 iomodel->FetchDataToInput(inputs,elements,"md.initialization.sealevel",SealevelEnum); 71 71 -
issm/trunk-jpl/src/c/classes/Elements/Tria.cpp
r26238 r26242 7169 7169 7170 7170 IssmDouble sealevel[3]={0}; 7171 int i,e,l,nbar; 7171 7172 7172 7173 if(loads->sealevelloads){ 7173 for(i nt i=0;i<NUMVERTICES;i++) {7174 for(i=0;i<NUMVERTICES;i++) { 7174 7175 if(slgeom->lids[this->vertices[i]->lid]!=this->lid)continue; 7175 for ( inte=0;e<nel;e++){7176 for (e=0;e<nel;e++){ 7176 7177 sealevel[i]+=G[i*nel+e]*(loads->sealevelloads[e]+loads->loads[e]); 7177 7178 } 7178 for( intl=0;l<SLGEOM_NUMLOADS;l++){7179 intnbar=slgeom->nbar[l];7180 for ( inte=0;e<nbar;e++){7179 for(l=0;l<SLGEOM_NUMLOADS;l++){ 7180 nbar=slgeom->nbar[l]; 7181 for (e=0;e<nbar;e++){ 7181 7182 sealevel[i]+=Gsub[l][i*nbar+e]*(loads->subloads[l][e]); 7182 7183 } 7183 7184 if(l==SLGEOM_OCEAN){ 7184 for ( inte=0;e<nbar;e++){7185 for (e=0;e<nbar;e++){ 7185 7186 sealevel[i]+=Gsub[l][i*nbar+e]*(loads->subsealevelloads[e]); 7186 7187 } … … 7190 7191 } 7191 7192 else{ //this is the initial convolution where only loads are provided 7192 for(i nt i=0;i<NUMVERTICES;i++) {7193 for(i=0;i<NUMVERTICES;i++) { 7193 7194 if(slgeom->lids[this->vertices[i]->lid]!=this->lid)continue; 7194 for ( inte=0;e<nel;e++){7195 for (e=0;e<nel;e++){ 7195 7196 sealevel[i]+=G[i*nel+e]*(loads->loads[e]); 7196 7197 } 7197 for( intl=0;l<SLGEOM_NUMLOADS;l++){7198 intnbar=slgeom->nbar[l];7199 for ( inte=0;e<nbar;e++){7198 for(l=0;l<SLGEOM_NUMLOADS;l++){ 7199 nbar=slgeom->nbar[l]; 7200 for (e=0;e<nbar;e++){ 7200 7201 sealevel[i]+=Gsub[l][i*nbar+e]*(loads->subloads[l][e]); 7201 7202 } … … 7206 7207 /*store values computed on vertices, but don't repeat the computation if another element already computed it!:*/ 7207 7208 if(percpu){ 7208 for(i nt i=0;i<NUMVERTICES;i++){7209 for(i=0;i<NUMVERTICES;i++){ 7209 7210 if(slgeom->lids[this->vertices[i]->lid]==this->lid)sealevelout[this->vertices[i]->lid]=sealevel[i]; 7210 7211 } 7211 7212 } 7212 7213 else{ 7213 for(i nt i=0;i<NUMVERTICES;i++) sealevelout[i]=sealevel[i];7214 for(i=0;i<NUMVERTICES;i++) sealevelout[i]=sealevel[i]; 7214 7215 } 7215 7216 -
issm/trunk-jpl/src/c/classes/ExternalResults/GenericExternalResult.h
r25531 r26242 679 679 #endif 680 680 681 /*Specific instantiations for IssmComplex*: */ 682 template <> inline GenericExternalResult<IssmComplex*>::GenericExternalResult(int in_id, int in_enum_type,IssmComplex* in_values, int in_M,int in_N,int in_step,IssmDouble in_time){/*{{{*/ 683 684 id = in_id; 685 M = in_M; 686 N = in_N; 687 688 EnumToStringx(&this->result_name,in_enum_type); 689 690 step = in_step; 691 time = in_time; 692 693 /*Copy result in values*/ 694 if(M*N){ 695 value=xNew<IssmComplex>(M*N); 696 xMemCpy<IssmComplex>(value,in_values,M*N); 697 } 698 else value=NULL; 699 } 700 /*}}}*/ 701 template <> inline void GenericExternalResult<IssmComplex*>::WriteData(FILE* fid,bool io_gather){ /*{{{*/ 702 703 int my_rank; 704 int type; 705 int rows,cols; 706 char *name = NULL; 707 IssmPDouble passiveDouble; 708 IssmDouble* reals=NULL; 709 IssmDouble* imags=NULL; 710 711 /*recover my_rank:*/ 712 my_rank=IssmComm::GetRank(); 713 714 if(io_gather){ 715 /*we are gathering the data on cpu 0, don't write on other cpus: */ 716 if(my_rank) return; 717 } 718 719 /*First write enum: */ 720 int length=(strlen(this->result_name)+1)*sizeof(char); 721 fwrite(&length,sizeof(int),1,fid); 722 fwrite(this->result_name,length,1,fid); 723 724 /*Now write time and step: */ 725 passiveDouble=reCast<IssmPDouble>(time); 726 fwrite(&passiveDouble,sizeof(IssmPDouble),1,fid); 727 fwrite(&step,sizeof(int),1,fid); 728 729 /*writing a IssmComplex array, type is 3:*/ 730 type=5; 731 fwrite(&type,sizeof(int),1,fid); 732 rows=this->M; 733 fwrite(&rows,sizeof(int),1,fid); 734 cols=this->N; 735 fwrite(&cols,sizeof(int),1,fid); 736 737 /*write complex array into two real arrays:*/ 738 reals=xNew<IssmDouble>(cols*rows); 739 imags=xNew<IssmDouble>(cols*rows); 740 for(int i=0;i<cols*rows;i++){ 741 reals[i]=value[i].real(); 742 imags[i]=value[i].imag(); 743 } 744 fwrite(reals,cols*rows*sizeof(IssmComplex),1,fid); 745 fwrite(imags,cols*rows*sizeof(IssmComplex),1,fid); 746 747 } 748 /*}}}*/ 749 681 750 /*Specifics instantiations for Vector*/ 682 751 template <> inline GenericExternalResult<Vector<IssmPDouble>*>::GenericExternalResult(int in_id, int in_enum_type,Vector<IssmPDouble>* in_values, int in_M,int in_N,int in_step,IssmDouble in_time){/*{{{*/ -
issm/trunk-jpl/src/c/cores/love_core.cpp
r26237 r26242 9 9 #include "../modules/modules.h" 10 10 #include "../solutionsequences/solutionsequences.h" 11 #include <petscblaslapack.h> 12 13 void love_init(FemModel* femmodel, Matlitho* matlitho){/*{{{*/ 14 // initialize Planet_Mass(r) for efficient computation of gravity, value of surface gravity and inital size of the yi equation system 15 bool verbosemod = (int)VerboseModule(); 16 17 int numlayers = matlitho->numlayers; 18 IssmDouble* r=matlitho->radius; 19 IssmDouble* EarthMass=xNewZeroInit<IssmDouble>(numlayers+1); 20 IssmDouble r1,r2,ro, GG; 21 femmodel->parameters->FindParam(&GG,LoveGravitationalConstantEnum); 22 23 for (int i=0;i<numlayers;i++){ 24 r2 = r[i+1]; 25 ro = matlitho->density[i]; 26 if (i==0){ 27 EarthMass[i] = ro*pow(r2,3.0)*4.0*PI/3.0; 28 }else{ 29 r1=r[i]; 30 EarthMass[i] = EarthMass[i-1] + ro*(pow(r2,3.0)-pow(r1,3.0))*4.0*PI/3.0;; 31 } 32 } 33 34 IssmDouble g0=EarthMass[numlayers-1]*GG/pow(r[numlayers],2.0); 35 femmodel->parameters->SetParam(g0,LoveG0Enum); 36 femmodel->parameters->SetParam(EarthMass,numlayers,LoveEarthMassEnum); 37 xDelete<IssmDouble>(EarthMass); 38 39 int nyi=6*(numlayers+1); 40 int starting_layer=0; 41 femmodel->parameters->SetParam(nyi,LoveNYiEquationsEnum); 42 femmodel->parameters->SetParam(starting_layer,LoveStartingLayerEnum); 43 }/*}}}*/ 44 void GetEarthRheology(IssmDouble* pla, IssmDouble* pmu, int layer_index, IssmDouble omega,FemModel* femmodel, Matlitho* matlitho){ /*{{{*/ 11 #include "petscblaslapack.h" 12 13 /*local definitions:*/ 14 class LoveVariables{ /*{{{*/ 15 16 public: 17 IssmDouble g0; 18 IssmDouble r0; 19 IssmDouble* EarthMass; 20 int nyi; 21 int starting_layer; 22 23 LoveVariables(){ /*{{{*/ 24 g0=0; 25 r0=0; 26 EarthMass=NULL; 27 nyi=0; 28 starting_layer=0; 29 } /*}}}*/ 30 LoveVariables(IssmDouble* EarthMassin,IssmDouble g0in,IssmDouble r0in,int nyiin,int starting_layerin){ /*{{{*/ 31 EarthMass=EarthMassin; 32 g0=g0in; 33 r0=r0in; 34 nyi=nyiin; 35 starting_layer=starting_layerin; 36 } /*}}}*/ 37 ~LoveVariables(){}; 38 }; /*}}}*/ 39 40 /*self contained support routines used by cores below:*/ 41 template<typename doubletype> doubletype angular_frequency(IssmDouble frequency); //pure declaration 42 template <> IssmDouble angular_frequency<IssmDouble>(IssmDouble frequency){ /*{{{*/ 43 return 2.0*PI*frequency; 44 } /*}}}*/ 45 template <> IssmComplex angular_frequency<IssmComplex>(IssmDouble frequency){ /*{{{*/ 46 IssmComplex value=reCast<IssmComplex>(complex<double>(0,1))*2.0*PI*reCast<IssmComplex>(frequency); 47 return value; 48 } /*}}}*/ 49 template<typename doubletype> void allgesv(int* pnyi, int* pnrhs, doubletype* yilocal, int* plda, int* ipiv, doubletype* rhslocal, int* pldb, int* pinfo); 50 template <> void allgesv<IssmDouble>(int* pnyi, int* pnrhs, IssmDouble* yilocal, int* plda, int* ipiv, IssmDouble* rhslocal, int* pldb, int* pinfo){ /*{{{*/ 51 dgesv_(pnyi, pnrhs, yilocal, plda, ipiv, rhslocal, pldb, pinfo); 52 } /*}}}*/ 53 template <> void allgesv<IssmComplex>(int* pnyi, int* pnrhs, IssmComplex* yilocal, int* plda, int* ipiv, IssmComplex* rhslocal, int* pldb, int* pinfo){ /*{{{*/ 54 _error_("zgesv_ not linked correctly yet! "); 55 //zgesv_(pnyi, pnrhs, yilocal, plda, ipiv, rhslocal, pldb, pinfo); 56 } /*}}}*/ 57 template<typename doubletype> doubletype factorial(int n){ /*{{{*/ 58 doubletype prod=1; 59 for (int i=2;i<n+1;i++) prod*=i; 60 return prod; 61 }/*}}}*/ 62 template<typename doubletype> doubletype n_C_r(int n, int r){ /*{{{*/ 63 //n choose r 64 int primes[169] = 65 {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 66 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 67 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 68 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 69 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 70 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 71 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 72 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 73 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 74 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 75 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 76 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 77 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 78 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 79 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 80 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 81 947, 953, 967, 971, 977, 983, 991, 997, 1009}; 82 int num, den; 83 num = 1; 84 den = 1; 85 86 for (int i=0;i<r;i++){ 87 num = num*(n-i); 88 den = den*(i+1); 89 if (i>0) { 90 // Divide out common prime factors 91 for (int k=0;k<169;k++){ //169 is the length of the prime vector here 92 if ( i % primes[k] == 0) { // modulo 93 num = num/primes[k]; 94 den = den/primes[k]; 95 } 96 } 97 } 98 } 99 100 doubletype res; 101 return res = num/den; 102 }/*}}}*/ 103 template<typename doubletype> doubletype* postwidder_coef(int NTit){ /*{{{*/ 104 //Coefficients of the Post-Widder method through Saltzer summation for inverse Laplace transform: 105 //The Mth iteration estimate will be: f(t)_M = sum_{k=1:2*M}(xi_[M,k] * f(s_k)) 106 //The method is based on equations (2), (6), (7) in: 107 //Valko PP, Abate J. Comparison of sequence accelerators for the Gaver method of numerical Laplace transform inversion. Computational Mathematics and Applications. (2004) 108 //Note that the coefficients xi lack the factor s=k*log(2)/t. 109 //That is because we are computing the heaviside response of the system rather than its impulse response, 110 //and Laplace_Transform(Heaviside(t).*f(t)) = f(s)/s. So s cancels out in the sum for f(t)_M. 111 112 doubletype* xi=xNewZeroInit<doubletype>(2*NTit*NTit); 113 int indxi; 114 for (int M=1;M<NTit+1;M++){ 115 for (int k=1;k<2*M+1;k++){ 116 indxi=(M-1)*(2*NTit)+k-1; 117 for (int j=floor((k+1)/2);j<min(k,M)+1;j++){ 118 xi[indxi]+=pow(j,M+1.0)/factorial<doubletype>(M)*n_C_r<doubletype>(M,j)*n_C_r<doubletype>(2*j,j)*n_C_r<doubletype>(j,k-j); 119 } 120 xi[indxi]*=pow(-1.0,k+M)/k; 121 } 122 } 123 return xi; 124 }/*}}}*/ 125 template<typename doubletype> void postwidder_transform(doubletype* Lovet, doubletype* Lovef,int d, int t, int NTit, doubletype* xi, FemModel* femmodel){ /*{{{*/ 126 //Computes Lovet for time step t and degree d from the PW coefficients xi and the corresponding 2*NTit frequency samples in Lovef 127 128 int nfreq, indxi, indf; 129 femmodel->parameters->FindParam(&nfreq,LoveNfreqEnum); 130 int nt=nfreq/2/NTit; 131 132 indf=d*nfreq+t*2*NTit; 133 doubletype LoveM[NTit]; 134 135 for (int M=1;M<NTit+1;M++){ 136 LoveM[M-1]=0.0; 137 for (int k=1;k<2*M+1;k++){ 138 indxi=(M-1)*(2*NTit)+k-1; 139 LoveM[M-1]+=xi[indxi]*Lovef[indf+k-1]; 140 } 141 142 //Make sure we are not getting into numerical instability 143 //Diverging once: ok, we'll give that the benefit of the doubt, it can be an inflexion point in the convergence series 144 //Diverging twice in a row: we are definitely propagating numerical error: revert to the last stable value and exit 145 if (M>3){ 146 if ( abs(LoveM[M-1]-LoveM[M-2]) > abs(LoveM[M-2]-LoveM[M-3]) && 147 abs(LoveM[M-2]-LoveM[M-3]) > abs(LoveM[M-3]-LoveM[M-4]) ){ 148 Lovet[d*nt+t]=LoveM[M-3]; 149 return; 150 } 151 } 152 } 153 Lovet[d*nt+t]=LoveM[NTit-1]; 154 }/*}}}*/ 155 template <typename doubletype> void GetEarthRheology(doubletype* pla, doubletype* pmu, int layer_index, doubletype omega, Matlitho* matlitho){ /*{{{*/ 45 156 46 157 //returns lame parameters (material rigity) lambda and mu for the right frequency and layer 47 IssmDouble vi=matlitho->viscosity[layer_index]; 48 IssmDouble mu=matlitho->lame_mu[layer_index]; 49 IssmDouble la=matlitho->lame_lambda[layer_index]; 50 int rheo=matlitho->rheologymodel[layer_index]; 158 doubletype mu,la; 159 160 IssmDouble vi=matlitho->viscosity[layer_index]; 161 IssmDouble mu0=matlitho->lame_mu[layer_index]; 162 IssmDouble la0=matlitho->lame_lambda[layer_index]; 163 int rheo=matlitho->rheologymodel[layer_index]; 51 164 52 165 if (vi!=0 && omega!=0.0){ //take into account viscosity in the rigidity if the material isn't a perfect fluid 53 54 IssmDouble ka=la + 2.0/3.0*mu; //Bulk modulus166 //Otherwise return the elastic value 167 IssmDouble ka=la0 + 2.0/3.0*mu0; //Bulk modulus 55 168 if (rheo==2){//EBM 56 169 IssmDouble alpha=matlitho->ebm_alpha[layer_index]; … … 58 171 IssmDouble taul=matlitho->ebm_taul[layer_index]; 59 172 IssmDouble tauh=matlitho->ebm_tauh[layer_index]; 60 IssmDouble hf1,hf2,U1,U2; 173 IssmDouble hf1,hf2; 174 doubletype U1,U2; 61 175 IssmDouble* a=xNew<IssmDouble>(2); 62 176 IssmDouble* b=xNew<IssmDouble>(1); … … 79 193 80 194 mu=mu/(1.0+ alpha*delta/(pow(tauh,alpha)-pow(taul,alpha))*(U1 + omega*U2) -mu/vi/omega); 81 195 la=ka-2.0/3.0*mu; 82 196 83 197 xDelete<IssmDouble>(a); … … 88 202 IssmDouble mu2=matlitho->burgers_mu[layer_index]; 89 203 90 mu=mu*omega*(omega+mu2/vi2)/((omega+mu2/vi2)*(omega+mu/vi)+mu/vi2*omega);91 la=ka-2.0/3.0*mu;92 204 mu=mu0*omega*(omega+mu2/vi2)/((omega+mu2/vi2)*(omega+mu0/vi)+mu0/vi2*omega); 205 la=ka-2.0/3.0*mu0; 206 } 93 207 else{//Maxwell 94 la = (la + mu*ka/vi/omega)/(1.0 + mu/vi/omega);95 mu = mu /(1.0+mu/vi/omega);96 } 97 98 99 100 208 la = (la0 + mu0*ka/vi/omega)/(1.0 + mu0/vi/omega); 209 mu = mu0/(1.0+mu0/vi/omega); 210 } 211 } 212 213 *pla=la; 214 *pmu=mu; 101 215 102 216 } /*}}}*/ 103 IssmDouble GetGravity(IssmDouble r2, int layer_index, FemModel* femmodel, Matlitho* matlitho){ /*{{{*/217 IssmDouble GetGravity(IssmDouble r2, int layer_index, FemModel* femmodel, Matlitho* matlitho,LoveVariables* vars){ /*{{{*/ 104 218 //computes gravity at radius r2 105 219 IssmDouble* EarthMass; 106 220 IssmDouble g, GG; 107 221 108 femmodel->parameters->FindParam(&EarthMass,&matlitho->numlayers,LoveEarthMassEnum);222 EarthMass=vars->EarthMass; 109 223 femmodel->parameters->FindParam(&GG,LoveGravitationalConstantEnum); 110 224 IssmDouble ro=matlitho->density[layer_index]; … … 120 234 return g= GG*M/pow(r2,2.0); 121 235 }/*}}}*/ 122 void fill_yi_prefactor(IssmDouble* yi_prefactor, int* pdeg, IssmDouble* pomega, FemModel* femmodel, Matlitho* matlitho){ /*{{{*/236 template <typename doubletype> void fill_yi_prefactor(doubletype* yi_prefactor, int* pdeg, doubletype* pomega, FemModel* femmodel, Matlitho* matlitho, LoveVariables* vars){ /*{{{*/ 123 237 //precalculates partial derivative factors for function yi_derivatives 124 IssmDouble ra=matlitho->radius[matlitho->numlayers]; 125 IssmDouble g0,r0,mu0, GG; 126 int nstep,nindex, starting_layer; 127 femmodel->parameters->FindParam(&g0,LoveG0Enum); 128 femmodel->parameters->FindParam(&r0,LoveR0Enum); 129 femmodel->parameters->FindParam(&mu0,LoveMu0Enum); 130 femmodel->parameters->FindParam(&GG,LoveGravitationalConstantEnum); 131 femmodel->parameters->FindParam(&nstep,LoveIntStepsPerLayerEnum); 132 femmodel->parameters->FindParam(&starting_layer,LoveStartingLayerEnum); 133 134 IssmDouble frh,frhg0,fgr0,fgr,fn,rm0,rlm,flm; 135 IssmDouble xmin,xmax,x,dr; 136 IssmDouble g,ro, issolid; 238 IssmDouble ra=matlitho->radius[matlitho->numlayers]; 239 IssmDouble g0,r0,mu0, GG; 240 int nstep,nindex, starting_layer; 241 242 femmodel->parameters->FindParam(&mu0,LoveMu0Enum); 243 femmodel->parameters->FindParam(&GG,LoveGravitationalConstantEnum); 244 femmodel->parameters->FindParam(&nstep,LoveIntStepsPerLayerEnum); 245 246 g0=vars->g0; 247 r0=vars->r0; 248 starting_layer=vars->starting_layer; 249 250 doubletype frh,frhg0,fgr0,fgr,fn,rm0,rlm,flm; 251 IssmDouble xmin,xmax,x,dr; 252 IssmDouble g,ro, issolid; 137 253 138 254 if (pomega) { //frequency and degree dependent terms /*{{{*/ 139 IssmDouble la,mu;140 IssmDouble* f=xNewZeroInit<IssmDouble>(12);255 doubletype la,mu; 256 doubletype f[12]; 141 257 int deg=*pdeg; 142 IssmDouble omega=*pomega;258 doubletype omega=*pomega; 143 259 fn=deg*(deg+1.0); 144 260 145 261 for (int layer_index=starting_layer;layer_index<matlitho->numlayers;layer_index++){ 146 262 147 148 149 150 GetEarthRheology(&la, &mu,layer_index,omega,femmodel,matlitho);151 263 ro=matlitho->density[layer_index]; 264 issolid=matlitho->issolid[layer_index]; 265 if(issolid==1){ 266 GetEarthRheology<doubletype>(&la, &mu,layer_index,omega,matlitho); 267 152 268 /*_______Expressions*/ 153 269 flm=(la+2.0*mu); … … 172 288 xmax=(matlitho->radius[layer_index+1])/ra; 173 289 dr = (xmax -xmin)/nstep; 174 290 x=xmin; 175 291 for (int n=0;n<nstep;n++){ 176 g=GetGravity(x*ra,layer_index,femmodel,matlitho );292 g=GetGravity(x*ra,layer_index,femmodel,matlitho,vars); 177 293 178 294 nindex=layer_index*nstep*36+n*36; … … 191 307 } 192 308 } 193 194 xDelete<IssmDouble>(f); 195 /*}}}*/ 309 /*}}}*/ 196 310 } else if (pdeg) { // degree dependent terms /*{{{*/ 197 198 311 int deg=*pdeg; 312 fn=(deg*(deg+1.0)); 199 313 200 314 for (int layer_index=starting_layer;layer_index<matlitho->numlayers;layer_index++){ 201 315 ro=matlitho->density[layer_index]; 202 316 issolid=matlitho->issolid[layer_index]; 203 317 204 318 /*_______Expressions*/ 205 319 fgr=4.0*PI*GG*ro*ra; 206 320 207 321 xmin=matlitho->radius[layer_index]/ra; 208 322 xmax=(matlitho->radius[layer_index+1])/ra; 209 323 dr = (xmax -xmin)/nstep; 210 324 x=xmin; 211 325 for (int n=0;n<nstep;n++){ 212 213 g=GetGravity(x*ra,layer_index,femmodel,matlitho);214 215 216 217 218 219 220 221 326 nindex=layer_index*nstep*36+n*36; 327 g=GetGravity(x*ra,layer_index,femmodel,matlitho,vars); 328 329 if(issolid==1){ 330 yi_prefactor[nindex+ 1*6+3]= fn/x; // in dy[1*6+3] 331 yi_prefactor[nindex+ 5*6+2]= -(fgr/g0*fn)/x; // in dy[5*6+2] 332 yi_prefactor[nindex+ 5*6+4]= fn/(x*x); // in dy[5*6+4] 333 } else { 334 yi_prefactor[nindex+ 1*6+0]= (-4.0*(fgr/g)+fn/x)/x; // in dy[1*6+0] liquid layer 335 } 222 336 x=x+dr; 223 337 } 224 338 } 225 /*}}}*/339 /*}}}*/ 226 340 } else { // static terms /*{{{*/ 227 341 for (int layer_index=starting_layer;layer_index<matlitho->numlayers;layer_index++){ 228 342 ro=matlitho->density[layer_index]; 229 343 issolid=matlitho->issolid[layer_index]; 230 344 231 345 /*_______Expressions*/ 232 346 frhg0=ro*g0*ra/mu0; … … 236 350 xmax=(matlitho->radius[layer_index+1])/ra; 237 351 dr = (xmax -xmin)/nstep; 238 239 240 g=GetGravity(x*ra,layer_index,femmodel,matlitho);241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 352 x=xmin; 353 for (int n=0;n<nstep;n++){ 354 g=GetGravity(x*ra,layer_index,femmodel,matlitho,vars); 355 nindex=layer_index*nstep*36+n*36; 356 if(issolid==1){ 357 yi_prefactor[nindex+ 1*6+5]= -frhg0; // in dy[1*6+5] 358 yi_prefactor[nindex+ 2*6+0]= -1.0/x; // in dy[2*6+0] 359 yi_prefactor[nindex+ 2*6+2]= 1.0/x; // in dy[2*6+2] 360 yi_prefactor[nindex+ 3*6+3]= -3.0/x; // in dy[3*6+3] 361 yi_prefactor[nindex+ 3*6+4]= -frhg0/x; // in dy[3*6+4] 362 yi_prefactor[nindex+ 4*6+0]= fgr/g0; // in dy[4*6+0] 363 yi_prefactor[nindex+ 4*6+5]= 1.0; // in dy[4*6+5] 364 yi_prefactor[nindex+ 5*6+5]= -2.0/x; // in dy[5*6+5] 365 } else { 366 yi_prefactor[nindex+ 0*6+0]= fgr/g; // in dy[0*6+0] liquid layer 367 yi_prefactor[nindex+ 0*6+1]= 1.0; // in dy[0*6+1] liquid layer 368 yi_prefactor[nindex+ 1*6+1]= -2.0/x-fgr/g; // in dy[1*6+1] liquid layer 369 } 256 370 x=x+dr; 257 371 } 258 372 } 259 /*}}}*/260 } 261 }/*}}}*/ 262 IssmDouble* yi_derivatives(IssmDouble* y, int layer_index, int n, IssmDouble* yi_prefactor, FemModel* femmodel, Matlitho* matlitho){ /*{{{*/373 /*}}}*/ 374 } 375 }/*}}}*/ 376 template <typename doubletype> void yi_derivatives(doubletype* dydx, doubletype* y, int layer_index, int n, doubletype* yi_prefactor, FemModel* femmodel, Matlitho* matlitho){ /*{{{*/ 263 377 //computes yi derivatives at r=radius[layer_index]+ n/nstep*(radius[layer_index+1]-radius[layer_index]) 264 378 265 379 IssmDouble issolid=matlitho->issolid[layer_index]; 266 380 int iy,id,ny, nindex, nstep; 267 IssmDouble* dydx=xNewZeroInit<IssmDouble>(6);268 IssmDouble* dy=xNewZeroInit<IssmDouble>(36);269 381 femmodel->parameters->FindParam(&nstep,LoveIntStepsPerLayerEnum); 270 382 271 383 /*{{{*/ /* For reference: 272 flm=(la+2.0*mu);273 rlm=(3.0*la+2.0*mu)/(la+2.0*mu);274 rm0=mu/mu0;275 rg0=g/g0;276 frh=ro*g*ra/mu0;277 fgr=4.0*PI*GG*ro*ra/g0;278 fn=(deg*(deg+1.0));279 280 281 if(issolid==1){282 ny = 6;283 284 dy[0*6+0]= (-2.0*la/flm)/x;285 dy[0*6+1]= mu0/flm;286 dy[0*6+2]= (la*fn/flm)/x;287 dy[0*6+3]= 0.0;288 dy[0*6+4]= 0.0;289 dy[0*6+5]= 0.0;290 291 dy[1*6+0]= 4.0*(-frh+rm0*rlm/x)/x + ro*pow(omega,2.0)*ra/mu0;292 dy[1*6+1]=(-4.0*mu/flm)/x;293 dy[1*6+2]= fn*(frh-2.0*rm0*rlm/x)/x;294 dy[1*6+3]= fn/x;295 dy[1*6+4]= 0.0;296 dy[1*6+5]= -frh/rg0;297 298 dy[2*6+0]= -1.0/x;299 dy[2*6+1]= 0.0;300 dy[2*6+2]= 1.0/x;301 dy[2*6+3]= 1/rm0;302 dy[2*6+4]= 0.0;303 dy[2*6+5]= 0.0;304 305 dy[3*6+0]= (frh-2.0*rm0*rlm/x)/x;306 dy[3*6+1]= ( -la/flm)/x;307 dy[3*6+2]= (2.0*rm0*(la*(2.0*fn-1.0)+2.0*mu*(fn-1.0))/flm)/(x*x) + ro*pow(omega,2.0)*ra/mu0;308 dy[3*6+3]= -3.0/x;309 dy[3*6+4]= -(frh/rg0)/x;310 dy[3*6+5]= 0.0;311 312 dy[4*6+0]= fgr;313 dy[4*6+1]= 0.0;314 dy[4*6+2]= 0.0;315 dy[4*6+3]= 0.0;316 dy[4*6+4]= 0.0;317 dy[4*6+5]= 1.0;318 319 dy[5*6+0]= 0.0;320 dy[5*6+1]= 0.0;321 dy[5*6+2]= -(fgr*fn)/x;322 dy[5*6+3]= 0.0;323 dy[5*6+4]= fn/(x*x);324 dy[5*6+5]= -2.0/x;325 326 } else {327 ny = 2;328 329 dy[0*6+0]= fgr/rg0;330 dy[0*6+1]= 1.0;331 dy[1*6+0]= (-4.0*(fgr/rg0)+fn/x)/x;332 dy[1*6+1]= -2.0/x-fgr/rg0;333 }334 */ /*}}}*/335 336 337 338 339 340 341 342 384 flm=(la+2.0*mu); 385 rlm=(3.0*la+2.0*mu)/(la+2.0*mu); 386 rm0=mu/mu0; 387 rg0=g/g0; 388 frh=ro*g*ra/mu0; 389 fgr=4.0*PI*GG*ro*ra/g0; 390 fn=(deg*(deg+1.0)); 391 392 393 if(issolid==1){ 394 ny = 6; 395 396 dy[0*6+0]= (-2.0*la/flm)/x; 397 dy[0*6+1]= mu0/flm; 398 dy[0*6+2]= (la*fn/flm)/x; 399 dy[0*6+3]= 0.0; 400 dy[0*6+4]= 0.0; 401 dy[0*6+5]= 0.0; 402 403 dy[1*6+0]= 4.0*(-frh+rm0*rlm/x)/x + ro*pow(omega,2.0)*ra/mu0; 404 dy[1*6+1]=(-4.0*mu/flm)/x; 405 dy[1*6+2]= fn*(frh-2.0*rm0*rlm/x)/x; 406 dy[1*6+3]= fn/x; 407 dy[1*6+4]= 0.0; 408 dy[1*6+5]= -frh/rg0; 409 410 dy[2*6+0]= -1.0/x; 411 dy[2*6+1]= 0.0; 412 dy[2*6+2]= 1.0/x; 413 dy[2*6+3]= 1/rm0; 414 dy[2*6+4]= 0.0; 415 dy[2*6+5]= 0.0; 416 417 dy[3*6+0]= (frh-2.0*rm0*rlm/x)/x; 418 dy[3*6+1]= ( -la/flm)/x; 419 dy[3*6+2]= (2.0*rm0*(la*(2.0*fn-1.0)+2.0*mu*(fn-1.0))/flm)/(x*x) + ro*pow(omega,2.0)*ra/mu0; 420 dy[3*6+3]= -3.0/x; 421 dy[3*6+4]= -(frh/rg0)/x; 422 dy[3*6+5]= 0.0; 423 424 dy[4*6+0]= fgr; 425 dy[4*6+1]= 0.0; 426 dy[4*6+2]= 0.0; 427 dy[4*6+3]= 0.0; 428 dy[4*6+4]= 0.0; 429 dy[4*6+5]= 1.0; 430 431 dy[5*6+0]= 0.0; 432 dy[5*6+1]= 0.0; 433 dy[5*6+2]= -(fgr*fn)/x; 434 dy[5*6+3]= 0.0; 435 dy[5*6+4]= fn/(x*x); 436 dy[5*6+5]= -2.0/x; 437 438 } else { 439 ny = 2; 440 441 dy[0*6+0]= fgr/rg0; 442 dy[0*6+1]= 1.0; 443 dy[1*6+0]= (-4.0*(fgr/rg0)+fn/x)/x; 444 dy[1*6+1]= -2.0/x-fgr/rg0; 445 } 446 */ /*}}}*/ 447 448 if(issolid==1){ 449 ny = 6; 450 } else { 451 ny = 2; 452 } 453 454 for (id=0;id<ny;id++){ 343 455 for (iy=0;iy<ny;iy++){ 344 456 nindex=layer_index*nstep*36+n*36; 345 457 dydx[id]=dydx[id]+yi_prefactor[nindex+id*6+iy]*y[iy]; 346 } 347 } 348 xDelete<IssmDouble>(dy); 349 return dydx; 350 }/*}}}*/ 351 void propagate_yi_euler(IssmDouble* y, IssmDouble xmin, IssmDouble xmax, int layer_index, IssmDouble* yi_prefactor, FemModel* femmodel, Matlitho* matlitho){ /*{{{*/ 458 } 459 } 460 return; 461 }/*}}}*/ 462 template <typename doubletype> void propagate_yi_euler(IssmDouble* y, IssmDouble xmin, IssmDouble xmax, int layer_index, IssmDouble* yi_prefactor, FemModel* femmodel, Matlitho* matlitho){ /*{{{*/ 352 463 //yields this: if we have y[j]=1.0 and y[!j]=0.0 at the bottom of the layer, what is y at the top of the layer? 353 464 //euler method … … 355 466 femmodel->parameters->FindParam(&nstep,LoveIntStepsPerLayerEnum); 356 467 357 468 IssmDouble* dydx=xNewZeroInit<IssmDouble>(6); 358 469 IssmDouble dr = (xmax -xmin)/nstep; 359 360 361 dydx=yi_derivatives(y,layer_index, i,yi_prefactor,femmodel,matlitho);362 363 y[j]+=dydx[j]*dr;364 }365 366 470 IssmDouble x=xmin; 471 for(int i = 0;i<nstep;i++){ 472 yi_derivatives<doubletype>(dydx,y,layer_index, i,yi_prefactor,femmodel,matlitho); 473 for (int j=0;j<6;j++){ 474 y[j]+=dydx[j]*dr; 475 } 476 x = x + dr; 477 } 367 478 xDelete<IssmDouble>(dydx); 368 479 }/*}}}*/ 369 void propagate_yi_RK2(IssmDouble* y, IssmDouble xmin, IssmDouble xmax, int layer_index, IssmDouble* yi_prefactor, FemModel* femmodel, Matlitho* matlitho){ /*{{{*/480 template <typename doubletype> void propagate_yi_RK2(doubletype* y, IssmDouble xmin, IssmDouble xmax, int layer_index, doubletype* yi_prefactor, FemModel* femmodel, Matlitho* matlitho){ /*{{{*/ 370 481 //yields this: if we have y[j]=1.0 and y[!j]=0.0 at the bottom of the layer, what is y at the top of the layer? 371 482 //Implements Runge-Kutta 2nd order (midpoint method) … … 373 484 femmodel->parameters->FindParam(&nstep,LoveIntStepsPerLayerEnum); 374 485 375 IssmDouble* k1=xNewZeroInit<IssmDouble>(6);376 IssmDouble* k2=xNewZeroInit<IssmDouble>(6);377 IssmDouble* k3=xNewZeroInit<IssmDouble>(6);378 IssmDouble* k4=xNewZeroInit<IssmDouble>(6);379 IssmDouble* y1=xNewZeroInit<IssmDouble>(6);380 IssmDouble* y2=xNewZeroInit<IssmDouble>(6);381 IssmDouble* y3=xNewZeroInit<IssmDouble>(6);486 doubletype k1[6]={0}; 487 doubletype k2[6]={0}; 488 doubletype k3[6]={0}; 489 doubletype k4[6]={0}; 490 doubletype y1[6]={0}; 491 doubletype y2[6]={0}; 492 doubletype y3[6]={0}; 382 493 383 494 IssmDouble dr = (xmax -xmin)/nstep; 384 IssmDouble x=xmin; 385 for(int i = 0;i<nstep/2;i++){ 386 k1=yi_derivatives(y,layer_index, 2*i,yi_prefactor,femmodel,matlitho); 495 IssmDouble x=xmin; 496 497 for(int i = 0;i<nstep/2;i++){ 498 yi_derivatives<doubletype>(k1,y,layer_index, 2*i,yi_prefactor,femmodel,matlitho); 499 for (int j=0;j<6;j++) {y1[j]=y[j]+k1[j]*dr;} 500 yi_derivatives<doubletype>(k2,y1,layer_index, 2*i+1,yi_prefactor,femmodel,matlitho); 501 502 for (int j=0;j<6;j++){ 503 y[j]+=k2[j]*2.0*dr; 504 } 505 x = x + 2.0*dr; 506 } 507 }/*}}}*/ 508 template <typename doubletype> void propagate_yi_RK4(IssmDouble* y, IssmDouble xmin, IssmDouble xmax, int layer_index, IssmDouble* yi_prefactor, FemModel* femmodel, Matlitho* matlitho){ /*{{{*/ 509 //yields this: if we have y[j]=1.0 and y[!j]=0.0 at the bottom of the layer, what is y at the top of the layer? 510 //Implements Runge-Kutta 4th order 511 int nstep; 512 femmodel->parameters->FindParam(&nstep,LoveIntStepsPerLayerEnum); 513 514 IssmDouble* k1=xNewZeroInit<IssmDouble>(6); 515 IssmDouble* k2=xNewZeroInit<IssmDouble>(6); 516 IssmDouble* k3=xNewZeroInit<IssmDouble>(6); 517 IssmDouble* k4=xNewZeroInit<IssmDouble>(6); 518 IssmDouble* y1=xNewZeroInit<IssmDouble>(6); 519 IssmDouble* y2=xNewZeroInit<IssmDouble>(6); 520 IssmDouble* y3=xNewZeroInit<IssmDouble>(6); 521 522 IssmDouble dr = (xmax -xmin)/nstep; 523 IssmDouble x=xmin; 524 for(int i = 0;i<nstep/2-1;i++){ 525 yi_derivatives<doubletype>(k1,y,layer_index, 2*i,yi_prefactor,femmodel,matlitho); 526 for (int j=0;j<6;j++) {y1[j]=y[j]+k1[j]*dr;} 527 yi_derivatives<doubletype>(k2,y1,layer_index, 2*i+1,yi_prefactor,femmodel,matlitho); 528 for (int j=0;j<6;j++) {y2[j]=y[j]+k2[j]*dr;} 529 yi_derivatives<doubletype>(k3,y2,layer_index, 2*i+1,yi_prefactor,femmodel,matlitho); 530 for (int j=0;j<6;j++) {y3[j]=y[j]+k3[j]*2.0*dr;} 531 yi_derivatives<doubletype>(k4,y3,layer_index, 2*i+2,yi_prefactor,femmodel,matlitho); 532 533 for (int j=0;j<6;j++){ 534 y[j]+=(k1[j]+2.0*k2[j]+2.0*k3[j]+k4[j])/3.0*dr; 535 } 536 x = x + 2.0*dr; 537 } 538 539 //Last step: we don't know the derivative at xmax, so we will assume the values at xmax-dr 540 int i=nstep/2; 541 yi_derivatives<doubletype>(k1,y,layer_index, 2*i,yi_prefactor,femmodel,matlitho); 387 542 for (int j=0;j<6;j++) {y1[j]=y[j]+k1[j]*dr;} 388 k2=yi_derivatives(y1,layer_index, 2*i+1,yi_prefactor,femmodel,matlitho); 389 390 for (int j=0;j<6;j++){ 391 y[j]+=k2[j]*2.0*dr; 392 } 393 x = x + 2.0*dr; 394 } 543 yi_derivatives<doubletype>(k2,y1,layer_index, 2*i+1,yi_prefactor,femmodel,matlitho); 544 for (int j=0;j<6;j++) {y2[j]=y[j]+k2[j]*dr;} 545 yi_derivatives<doubletype>(k3,y2,layer_index, 2*i+1,yi_prefactor,femmodel,matlitho); 546 for (int j=0;j<6;j++) {y3[j]=y[j]+k3[j]*2.0*dr;} 547 yi_derivatives<doubletype>(k4,y3,layer_index, 2*i+1,yi_prefactor,femmodel,matlitho); 548 549 for (int j=0;j<6;j++){ 550 y[j]+=(k1[j]+2.0*k2[j]+2.0*k3[j]+k4[j])/3.0*dr; 551 } 552 553 x = x + 2.0*dr; 554 395 555 xDelete<IssmDouble>(k1); 396 556 xDelete<IssmDouble>(k2); … … 401 561 xDelete<IssmDouble>(y3); 402 562 }/*}}}*/ 403 void propagate_yi_RK4(IssmDouble* y, IssmDouble xmin, IssmDouble xmax, int layer_index, IssmDouble* yi_prefactor, FemModel* femmodel, Matlitho* matlitho){ /*{{{*/ 404 //yields this: if we have y[j]=1.0 and y[!j]=0.0 at the bottom of the layer, what is y at the top of the layer? 405 //Implements Runge-Kutta 4th order 406 int nstep; 407 femmodel->parameters->FindParam(&nstep,LoveIntStepsPerLayerEnum); 408 409 IssmDouble* k1=xNewZeroInit<IssmDouble>(6); 410 IssmDouble* k2=xNewZeroInit<IssmDouble>(6); 411 IssmDouble* k3=xNewZeroInit<IssmDouble>(6); 412 IssmDouble* k4=xNewZeroInit<IssmDouble>(6); 413 IssmDouble* y1=xNewZeroInit<IssmDouble>(6); 414 IssmDouble* y2=xNewZeroInit<IssmDouble>(6); 415 IssmDouble* y3=xNewZeroInit<IssmDouble>(6); 416 417 IssmDouble dr = (xmax -xmin)/nstep; 418 IssmDouble x=xmin; 419 for(int i = 0;i<nstep/2-1;i++){ 420 k1=yi_derivatives(y,layer_index, 2*i,yi_prefactor,femmodel,matlitho); 421 for (int j=0;j<6;j++) {y1[j]=y[j]+k1[j]*dr;} 422 k2=yi_derivatives(y1,layer_index, 2*i+1,yi_prefactor,femmodel,matlitho); 423 for (int j=0;j<6;j++) {y2[j]=y[j]+k2[j]*dr;} 424 k3=yi_derivatives(y2,layer_index, 2*i+1,yi_prefactor,femmodel,matlitho); 425 for (int j=0;j<6;j++) {y3[j]=y[j]+k3[j]*2.0*dr;} 426 k4=yi_derivatives(y3,layer_index, 2*i+2,yi_prefactor,femmodel,matlitho); 427 428 for (int j=0;j<6;j++){ 429 y[j]+=(k1[j]+2.0*k2[j]+2.0*k3[j]+k4[j])/3.0*dr; 430 } 431 x = x + 2.0*dr; 432 } 433 434 //Last step: we don't know the derivative at xmax, so we will assume the values at xmax-dr 435 int i=nstep/2; 436 k1=yi_derivatives(y,layer_index, 2*i,yi_prefactor,femmodel,matlitho); 437 for (int j=0;j<6;j++) {y1[j]=y[j]+k1[j]*dr;} 438 k2=yi_derivatives(y1,layer_index, 2*i+1,yi_prefactor,femmodel,matlitho); 439 for (int j=0;j<6;j++) {y2[j]=y[j]+k2[j]*dr;} 440 k3=yi_derivatives(y2,layer_index, 2*i+1,yi_prefactor,femmodel,matlitho); 441 for (int j=0;j<6;j++) {y3[j]=y[j]+k3[j]*2.0*dr;} 442 k4=yi_derivatives(y3,layer_index, 2*i+1,yi_prefactor,femmodel,matlitho); 443 444 for (int j=0;j<6;j++){ 445 y[j]+=(k1[j]+2.0*k2[j]+2.0*k3[j]+k4[j])/3.0*dr; 446 } 447 448 x = x + 2.0*dr; 449 450 xDelete<IssmDouble>(k1); 451 xDelete<IssmDouble>(k2); 452 xDelete<IssmDouble>(k3); 453 xDelete<IssmDouble>(k4); 454 xDelete<IssmDouble>(y1); 455 xDelete<IssmDouble>(y2); 456 xDelete<IssmDouble>(y3); 457 }/*}}}*/ 458 void Innersphere_boundaryconditions(IssmDouble* yi, int layer_index, int deg, IssmDouble omega, FemModel* femmodel, Matlitho* matlitho){ /*{{{*/ 563 template <typename doubletype> void Innersphere_boundaryconditions(doubletype* yi, int layer_index, int deg, doubletype omega, FemModel* femmodel, Matlitho* matlitho, LoveVariables* vars){ /*{{{*/ 459 564 //fills the boundary conditions at the bottom of layer[layer_index] in yi[0:2][0:5] 460 565 … … 463 568 IssmDouble g0,r0,mu0, GG; 464 569 int nyi; 465 femmodel->parameters->FindParam(&g0,LoveG0Enum); 466 femmodel->parameters->FindParam(&r0,LoveR0Enum); 467 femmodel->parameters->FindParam(&mu0,LoveMu0Enum); 468 femmodel->parameters->FindParam(&nyi,LoveNYiEquationsEnum); 570 571 femmodel->parameters->FindParam(&mu0,LoveMu0Enum); 469 572 femmodel->parameters->FindParam(&GG,LoveGravitationalConstantEnum); 573 574 g0=vars->g0; 575 r0=vars->r0; 576 nyi=vars->nyi; 577 470 578 IssmDouble ro=matlitho->density[layer_index]; 471 579 IssmDouble issolid=matlitho->issolid[layer_index]; 472 IssmDouble g=GetGravity(r,layer_index,femmodel,matlitho );473 IssmDouble la,mu;580 IssmDouble g=GetGravity(r,layer_index,femmodel,matlitho,vars); 581 doubletype la,mu; 474 582 475 583 if (layer_index==0){ 476 584 // radius[0] cannot be 0 for numerical reasons, but below our first interface at radius[0] would in reality be the same material as in the first layer 477 GetEarthRheology (&la, &mu,layer_index,omega,femmodel,matlitho);585 GetEarthRheology<doubletype>(&la, &mu,layer_index,omega,matlitho); 478 586 } else { 479 GetEarthRheology (&la, &mu,layer_index-1,omega,femmodel,matlitho);587 GetEarthRheology<doubletype>(&la, &mu,layer_index-1,omega,matlitho); 480 588 } 481 589 … … 506 614 yi[5+nyi*1]=-cst/(r*g0); 507 615 yi[5+nyi*2]=deg/(r*g0); 508 }/*}}}*/ 509 void build_yi_system(IssmDouble* yi, int deg, IssmDouble omega, IssmDouble* yi_prefactor, FemModel* femmodel, Matlitho* matlitho) { /*{{{*/ 616 617 }/*}}}*/ 618 template <typename doubletype> void build_yi_system(doubletype* yi, int deg, doubletype omega, doubletype* yi_prefactor, FemModel* femmodel, Matlitho* matlitho,LoveVariables* vars) { /*{{{*/ 510 619 511 620 IssmDouble g0,r0,mu0,x,ro1, GG; 512 621 int nyi,starting_layer, nstep; 513 femmodel->parameters->FindParam(&g0,LoveG0Enum); 514 femmodel->parameters->FindParam(&r0,LoveR0Enum); 622 623 g0=vars->g0; 624 r0=vars->r0; 625 nyi=vars->nyi; 626 starting_layer=vars->starting_layer; 627 515 628 femmodel->parameters->FindParam(&mu0,LoveMu0Enum); 516 femmodel->parameters->FindParam(&nyi,LoveNYiEquationsEnum);517 629 femmodel->parameters->FindParam(&GG,LoveGravitationalConstantEnum); 518 femmodel->parameters->FindParam(&starting_layer,LoveStartingLayerEnum);519 630 femmodel->parameters->FindParam(&nstep,LoveIntStepsPerLayerEnum); 520 631 521 522 632 IssmDouble xmin,xmax,one,ro,g; 633 IssmDouble ra=matlitho->radius[matlitho->numlayers]; 523 634 524 635 for (int i=0;i<6*(matlitho->numlayers+1);i++){ … … 529 640 530 641 int ny,is,ii,jj; 531 IssmDouble ystart[6];642 doubletype ystart[6]; 532 643 for (int k=0;k<6;k++) ystart[k]=0.0; 533 644 534 645 int ici = 0; // Index of current interface 535 646 for (int i = starting_layer; i<matlitho->numlayers;i++){ … … 538 649 xmax=(matlitho->radius[i+1])/ra; 539 650 540 651 541 652 if (matlitho->issolid[i]){ 542 543 544 653 ny = 6; 654 is = 0; 655 one= 1.0; 545 656 } else { 546 547 548 549 } 550 657 ny = 2; 658 is = 4; 659 one= -1.0; 660 } 661 551 662 552 663 for (int j = 0;j<ny;j++){ 553 664 for (int k=0;k<6;k++){ystart[k]=0.0;} 554 665 ystart[j]= 1.0; 555 666 556 667 // Numerical Integration 557 668 //propagate_yi_euler(&ystart[0], xmin, xmax, i, yi_prefactor,femmodel, matlitho); 558 propagate_yi_RK2 (&ystart[0], xmin, xmax, i, yi_prefactor,femmodel, matlitho);669 propagate_yi_RK2<doubletype>(&ystart[0], xmin, xmax, i, yi_prefactor,femmodel, matlitho); 559 670 //propagate_yi_RK4(&ystart[0], xmin, xmax, i, yi_prefactor,femmodel, matlitho); 560 671 // Boundary Condition matrix - propagation part … … 562 673 jj = 6*(ici+1)+j+is-3; 563 674 for (int kk=0;kk<ny;kk++){ 564 565 } 566 } 567 568 675 yi[(ii+kk)+nyi*jj] = ystart[kk]*one; 676 } 677 } 678 679 569 680 // Boundary Condition matrix - solid regions 570 681 if (matlitho->issolid[i]){ … … 576 687 } else { // Boundary Condition matrix - liquid regions 577 688 ro1=matlitho->density[i]; 578 g=GetGravity(matlitho->radius[i], i, femmodel,matlitho );689 g=GetGravity(matlitho->radius[i], i, femmodel,matlitho,vars); 579 690 ii = 6*ici; 580 691 yi[ii+nyi*(ii+3)] = -1.0; … … 585 696 yi[(ii+4)+nyi*(ii+4+3)]=-1.0; 586 697 yi[(ii+5)+nyi*(ii+5+3)]=-1.0; 587 g=GetGravity(matlitho->radius[i+1], i,femmodel,matlitho );698 g=GetGravity(matlitho->radius[i+1], i,femmodel,matlitho,vars); 588 699 ii = 6*(ici+1); 589 700 yi[ii+nyi*(ii-1)]=-1.0; 590 701 yi[ii+nyi*(ii+1)]=yi[(ii+4)+nyi*(ii+1)]*g0/g; // yi(17,14) solution integration 1 of z5 CMB 591 702 yi[ii+nyi*(ii+2)]=yi[(ii+4)+nyi*(ii+2)]*g0/g; // yi(17,15) solution integration 2 of z5 CMB 592 703 // yi(13,..) y1 CMB 593 704 yi[(ii+1)+nyi*(ii-1)]=-ro1*g*ra/mu0; 594 705 yi[(ii+2)+nyi*(ii)]=-1.0; … … 599 710 600 711 601 602 Innersphere_boundaryconditions (yi, starting_layer, deg, omega, femmodel, matlitho);603 604 712 //-- Internal sphere: integration starts here rather than r=0 for numerical reasons 713 Innersphere_boundaryconditions<doubletype>(yi, starting_layer, deg, omega, femmodel, matlitho,vars); 714 715 //-- Surface conditions 605 716 yi[(nyi-6)+nyi*(nyi-3)]=-1.0; 606 717 yi[(nyi-4)+nyi*(nyi-2)]=-1.0; … … 608 719 yi[(nyi-1)+nyi*(nyi-1)]=deg+1.0; 609 720 610 721 //-- Degree 1 special case 611 722 if(deg==1){ 612 723 for (int i=0;i<nyi;i++){ … … 615 726 yi[(nyi-1)+nyi*(nyi-1)]=1.0; 616 727 } 617 }/*}}}*/ 618 void yi_boundary_conditions(IssmDouble* yi_righthandside, int deg, FemModel* femmodel, Matlitho* matlitho){ /*{{{*/ 728 729 }/*}}}*/ 730 template <typename doubletype> void yi_boundary_conditions(doubletype* yi_righthandside, int deg, FemModel* femmodel, Matlitho* matlitho,LoveVariables* vars){ /*{{{*/ 619 731 620 732 IssmDouble g0,r0,mu0,ra,rb,rc; 621 int nyi, forcing_type,icb,cmb ;733 int nyi, forcing_type,icb,cmb,starting_layer; 622 734 IssmDouble* EarthMass; 623 femmodel->parameters->FindParam(&g0,LoveG0Enum); 624 femmodel->parameters->FindParam(&r0,LoveR0Enum); 735 736 g0=vars->g0; 737 r0=vars->r0; 738 nyi=vars->nyi; 739 starting_layer=vars->starting_layer; 740 EarthMass=vars->EarthMass; 741 625 742 femmodel->parameters->FindParam(&mu0,LoveMu0Enum); 626 femmodel->parameters->FindParam(&nyi,LoveNYiEquationsEnum);627 743 femmodel->parameters->FindParam(&forcing_type,LoveForcingTypeEnum); 628 744 femmodel->parameters->FindParam(&icb,LoveInnerCoreBoundaryEnum); 629 745 femmodel->parameters->FindParam(&cmb,LoveCoreMantleBoundaryEnum); 630 femmodel->parameters->FindParam(&EarthMass,&matlitho->numlayers,LoveEarthMassEnum); 631 632 // In Case of a Inner Core - Outer Core - Mantle planet and Boundary conditions on these 3 interfaces 746 747 // In Case of a Inner Core - Outer Core - Mantle planet and Boundary conditions on these 3 interfaces 633 748 ra=matlitho->radius[matlitho->numlayers]; 634 749 rb=0; … … 642 757 643 758 IssmDouble ro_mean=EarthMass[matlitho->numlayers-1]/(4.0/3.0*PI*pow(ra,3.0)); 644 xDelete<IssmDouble>(EarthMass);645 759 646 760 for (int i=0;i<(matlitho->numlayers+1)*6;i++) yi_righthandside[i]=0.0; … … 648 762 switch (forcing_type) { 649 763 650 //-- forcings at the Inner Core Boundary651 652 yi_righthandside[6*icb+5]=(deg)/(rc*g0);653 yi_righthandside[6*icb+4]=1.0/(ra*g0);654 break;655 case 2: //'ICB --Pressure'656 yi_righthandside[6*icb+1]=-ro_mean/mu0;657 break;658 case 3://'ICB --Loading'659 yi_righthandside[6*icb+1]=-ro_mean*(2.0*deg+1.0)/(3.0*mu0)*ra/rc;660 yi_righthandside[6*icb+5]= (2.0*deg+1.0)/(rc*g0);661 break;662 case 4://'ICB --Tangential Traction'663 yi_righthandside[6*icb+3]= ro_mean/mu0;664 break;665 666 //--forcings at the Core Mantle Boundary667 case 5://'CMB --Volumetric Potential'668 yi_righthandside[6*cmb+1]=-ro_mean/mu0*ra/rb;669 yi_righthandside[6*cmb+5]= (2.0*deg+1.0)/(rb*g0);670 break;671 case 6://'CMB --Pressure'672 yi_righthandside[6*cmb+1]=-ro_mean/mu0;673 break;674 case 7://'CMB --Loading'675 yi_righthandside[6*cmb+1]=-ro_mean*(2.0*deg+1.0)/(3.0*mu0)*ra/rb;676 yi_righthandside[6*cmb+5]= (2.0*deg+1.0)/(rb*g0);677 break;678 case 8://'CMB --Tangential Traction'679 yi_righthandside[6*cmb+3]=-ro_mean/mu0;680 break;681 682 //--forcings at the surface683 case 9://'SURF--Volumetric Potential'684 if (deg>1) yi_righthandside[nyi-1]=(2.0*deg+1.0)/(ra*g0);685 break;686 case 10://'SURF--Pressure'687 yi_righthandside[nyi-5]=-ro_mean/mu0;688 break;689 case 11://'SURF--Loading'690 yi_righthandside[nyi-5]=-ro_mean*(2.0*deg+1.0)/(3.0*mu0);691 if (deg>1) yi_righthandside[nyi-1]= (2.0*deg+1.0)/(ra*g0);692 break;693 case 12://'SURF--Tangential Traction'694 yi_righthandside[nyi-3]= ro_mean/mu0;695 break;696 default:697 _error_("love core error: forcing_type not supported yet");698 } 699 }/*}}}*/ 700 void solve_yi_system(IssmDouble* loveh, IssmDouble* lovel, IssmDouble* lovek, int deg, IssmDouble omega, IssmDouble* yi, IssmDouble* rhs, FemModel* femmodel, Matlitho* matlitho){ /*{{{*/764 //-- forcings at the Inner Core Boundary 765 case 1: //'ICB --Volumetric Potential' 766 yi_righthandside[6*icb+5]=(deg)/(rc*g0); 767 yi_righthandside[6*icb+4]=1.0/(ra*g0); 768 break; 769 case 2: //'ICB --Pressure' 770 yi_righthandside[6*icb+1]=-ro_mean/mu0; 771 break; 772 case 3://'ICB --Loading' 773 yi_righthandside[6*icb+1]=-ro_mean*(2.0*deg+1.0)/(3.0*mu0)*ra/rc; 774 yi_righthandside[6*icb+5]= (2.0*deg+1.0)/(rc*g0); 775 break; 776 case 4://'ICB --Tangential Traction' 777 yi_righthandside[6*icb+3]= ro_mean/mu0; 778 break; 779 780 //--forcings at the Core Mantle Boundary 781 case 5://'CMB --Volumetric Potential' 782 yi_righthandside[6*cmb+1]=-ro_mean/mu0*ra/rb; 783 yi_righthandside[6*cmb+5]= (2.0*deg+1.0)/(rb*g0); 784 break; 785 case 6://'CMB --Pressure' 786 yi_righthandside[6*cmb+1]=-ro_mean/mu0; 787 break; 788 case 7://'CMB --Loading' 789 yi_righthandside[6*cmb+1]=-ro_mean*(2.0*deg+1.0)/(3.0*mu0)*ra/rb; 790 yi_righthandside[6*cmb+5]= (2.0*deg+1.0)/(rb*g0); 791 break; 792 case 8://'CMB --Tangential Traction' 793 yi_righthandside[6*cmb+3]=-ro_mean/mu0; 794 break; 795 796 //--forcings at the surface 797 case 9://'SURF--Volumetric Potential' 798 if (deg>1) yi_righthandside[nyi-1]=(2.0*deg+1.0)/(ra*g0); 799 break; 800 case 10://'SURF--Pressure' 801 yi_righthandside[nyi-5]=-ro_mean/mu0; 802 break; 803 case 11://'SURF--Loading' 804 yi_righthandside[nyi-5]=-ro_mean*(2.0*deg+1.0)/(3.0*mu0); 805 if (deg>1) yi_righthandside[nyi-1]= (2.0*deg+1.0)/(ra*g0); 806 break; 807 case 12://'SURF--Tangential Traction' 808 yi_righthandside[nyi-3]= ro_mean/mu0; 809 break; 810 default: 811 _error_("love core error: forcing_type not supported yet"); 812 } 813 }/*}}}*/ 814 template <typename doubletype> void solve_yi_system(doubletype* loveh, doubletype* lovel, doubletype* lovek, int deg, doubletype omega, doubletype* yi, doubletype* rhs, FemModel* femmodel, Matlitho* matlitho, LoveVariables* vars){ /*{{{*/ 701 815 702 816 IssmDouble g0,r0,mu0,loveratio,underflow_tol; … … 704 818 int nyi,starting_layer, dummy; 705 819 bool allow_layer_deletion; 706 femmodel->parameters->FindParam(&g0,LoveG0Enum); 707 femmodel->parameters->FindParam(&r0,LoveR0Enum); 820 IssmDouble* EarthMass=NULL; 821 822 g0=vars->g0; 823 r0=vars->r0; 824 nyi=vars->nyi; 825 starting_layer=vars->starting_layer; 826 EarthMass=vars->EarthMass; 827 708 828 femmodel->parameters->FindParam(&mu0,LoveMu0Enum); 709 femmodel->parameters->FindParam(&nyi,LoveNYiEquationsEnum);710 femmodel->parameters->FindParam(&starting_layer,LoveStartingLayerEnum);711 829 femmodel->parameters->FindParam(&allow_layer_deletion,LoveAllowLayerDeletionEnum); 712 830 femmodel->parameters->FindParam(&underflow_tol,LoveUnderflowTolEnum); 713 831 femmodel->parameters->FindParam(&frequencies,&dummy,LoveFrequenciesEnum); 714 832 IssmDouble ra=matlitho->radius[matlitho->numlayers]; 715 833 bool exit=false; 716 834 int lda,ldb; … … 719 837 lda=nyi; 720 838 ldb=nyi; 721 IssmDouble* yilocal=xNew<IssmDouble>(nyi*nyi); // we will need to redeclare these inside here as nyi changes722 IssmDouble* rhslocal=xNew<IssmDouble>(nyi);839 doubletype* yilocal=xNew<doubletype>(nyi*nyi); // we will need to redeclare these inside here as nyi changes 840 doubletype* rhslocal=xNew<doubletype>(nyi); 723 841 724 842 //we need to do a local copy of yi,rhs to send them to LAPACK with the appropriate size and to keep the original matrices in case layers are deleted and we need to try again … … 734 852 int nrhs=1; // number of right hand size columns 735 853 736 dgesv_(&nyi, &nrhs, yilocal, &lda, ipiv, rhslocal, &ldb, &info); 854 allgesv<doubletype>(&nyi, &nrhs, yilocal, &lda, ipiv, rhslocal, &ldb, &info); 855 737 856 xDelete<int>(ipiv); 738 739 if(Verbose Solution() && info!=0){857 858 if(VerboseModule() && info!=0){ 740 859 _printf0_("love core warning in DGESV : LAPACK linear equation solver couldn't resolve the system"); 741 860 printf("%s %s %s %s\n", "i","j","yi[i+nyi*j]","rhs[i]"); … … 751 870 *lovek = rhslocal[nyi-1]*ra*g0; 752 871 753 IssmDouble loveh1 = rhslocal[3];754 IssmDouble lovel1 = rhslocal[5];755 IssmDouble lovek1 = rhslocal[7] - pow(matlitho->radius[starting_layer]/ra,deg)/(g0*ra);756 757 IssmDouble loveh1s = rhslocal[nyi-3];758 IssmDouble lovel1s = rhslocal[nyi-2];759 IssmDouble lovek1s = rhslocal[nyi-1] - 1.0/(g0*ra);872 doubletype loveh1 = rhslocal[3]; 873 doubletype lovel1 = rhslocal[5]; 874 doubletype lovek1 = rhslocal[7] - pow(matlitho->radius[starting_layer]/ra,deg)/(g0*ra); 875 876 doubletype loveh1s = rhslocal[nyi-3]; 877 doubletype lovel1s = rhslocal[nyi-2]; 878 doubletype lovek1s = rhslocal[nyi-1] - 1.0/(g0*ra); 760 879 761 880 loveratio = abs(loveh1/loveh1s); //ratio of center to surface love numbers, determines if we should remove layers … … 763 882 if (abs(lovek1/lovek1s) < loveratio) loveratio = abs(lovek1/lovek1s); 764 883 765 if (!allow_layer_deletion || nyi<=12 || omega!= 2.0*PI*frequencies[0]){ //We are not allowed to delete layers, or there is only one layer left. We also don't want to delete layers in the middle of a loop on frequencies, as that can lead to a jump that would compromise the inverse laplace transform.884 if (!allow_layer_deletion || nyi<=12 || omega!=angular_frequency<doubletype>(frequencies[0])){ 766 885 goto save_results; 886 /*We are not allowed to delete layers, or there is only one layer left. We also don't want to delete 887 layers in the middle of a loop on frequencies, as that can lead to a jump that would compromise the 888 inverse laplace transform.*/ 767 889 } 768 890 … … 775 897 nyi-=6; 776 898 starting_layer+=1; 777 femmodel->parameters->SetParam(nyi,LoveNYiEquationsEnum); 778 femmodel->parameters->SetParam(starting_layer,LoveStartingLayerEnum); 779 899 vars->nyi=nyi; 900 vars->starting_layer=starting_layer; 780 901 781 902 for (int i=0;i<nyi;i++){//shift everything down by 1 layer … … 786 907 } 787 908 788 Innersphere_boundaryconditions (yi, starting_layer, deg, omega, femmodel, matlitho); //we move the first interface to the new starting layer. yi[0:2,0:5] will be different909 Innersphere_boundaryconditions<doubletype>(yi, starting_layer, deg, omega, femmodel, matlitho,vars); //we move the first interface to the new starting layer. yi[0:2,0:5] will be different 789 910 } else { //we are ready to save the outputs and break the main loop 790 911 791 912 save_results: 792 913 for (int i=0;i<nyi;i++){ 793 914 rhs[i]=rhslocal[i]; … … 811 932 812 933 exit = true; 813 814 xDelete< IssmDouble>(yilocal);815 xDelete< IssmDouble>(rhslocal);816 934 } 935 xDelete<doubletype>(yilocal); 936 xDelete<doubletype>(rhslocal); 937 } 817 938 xDelete<IssmDouble>(frequencies); 818 }/*}}}*/ 819 IssmDouble factorial(int n){ /*{{{*/ 820 IssmDouble prod=1; 821 for (int i=2;i<n+1;i++) prod*=i; 822 return prod; 823 }/*}}}*/ 824 IssmDouble n_C_r(int n, int r){ /*{{{*/ 825 //n choose r 826 int primes[169] = 827 {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 828 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 829 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 830 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 831 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 832 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 833 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 834 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 835 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 836 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 837 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 838 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 839 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 840 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 841 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 842 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 843 947, 953, 967, 971, 977, 983, 991, 997, 1009}; 844 int num, den; 845 num = 1; 846 den = 1; 847 848 for (int i=0;i<r;i++){ 849 num = num*(n-i); 850 den = den*(i+1); 851 if (i>0) { 852 // Divide out common prime factors 853 for (int k=0;k<169;k++){ //169 is the length of the prime vector here 854 if ( i % primes[k] == 0) { // modulo 855 num = num/primes[k]; 856 den = den/primes[k]; 857 } 858 } 859 } 860 } 861 862 IssmDouble res; 863 return res = num/den; 864 }/*}}}*/ 865 IssmDouble* postwidder_coef(int NTit){ /*{{{*/ 866 //Coefficients of the Post-Widder method through Saltzer summation for inverse Laplace transform: 867 //The Mth iteration estimate will be: f(t)_M = sum_{k=1:2*M}(xi_[M,k] * f(s_k)) 868 //The method is based on equations (2), (6), (7) in: 869 //Valko PP, Abate J. Comparison of sequence accelerators for the Gaver method of numerical Laplace transform inversion. Computational Mathematics and Applications. (2004) 870 //Note that the coefficients xi lack the factor s=k*log(2)/t. 871 //That is because we are computing the heaviside response of the system rather than its impulse response, 872 //and Laplace_Transform(Heaviside(t).*f(t)) = f(s)/s. So s cancels out in the sum for f(t)_M. 873 874 IssmDouble* xi=xNewZeroInit<IssmDouble>(2*NTit*NTit); 875 int indxi; 876 for (int M=1;M<NTit+1;M++){ 877 for (int k=1;k<2*M+1;k++){ 878 indxi=(M-1)*(2*NTit)+k-1; 879 for (int j=floor((k+1)/2);j<min(k,M)+1;j++){ 880 xi[indxi]+=pow(j,M+1.0)/factorial(M)*n_C_r(M,j)*n_C_r(2*j,j)*n_C_r(j,k-j); 881 } 882 xi[indxi]*=pow(-1.0,k+M)/k; 883 } 884 } 885 return xi; 886 }/*}}}*/ 887 void postwidder_transform(IssmDouble* Lovet, IssmDouble* Lovef,int d, int t, int NTit, IssmDouble* xi, FemModel* femmodel){ /*{{{*/ 888 //Computes Lovet for time step t and degree d from the PW coefficients xi and the corresponding 2*NTit frequency samples in Lovef 889 890 int nfreq, indxi, indf; 891 femmodel->parameters->FindParam(&nfreq,LoveNfreqEnum); 892 int nt=nfreq/2/NTit; 893 894 indf=d*nfreq+t*2*NTit; 895 IssmDouble LoveM[NTit]; 896 897 for (int M=1;M<NTit+1;M++){ 898 LoveM[M-1]=0.0; 899 for (int k=1;k<2*M+1;k++){ 900 indxi=(M-1)*(2*NTit)+k-1; 901 LoveM[M-1]+=xi[indxi]*Lovef[indf+k-1]; 902 } 903 904 //Make sure we are not getting into numerical instability 905 //Diverging once: ok, we'll give that the benefit of the doubt, it can be an inflexion point in the convergence series 906 //Diverging twice in a row: we are definitely propagating numerical error: revert to the last stable value and exit 907 if (M>3){ 908 if ( abs(LoveM[M-1]-LoveM[M-2]) > abs(LoveM[M-2]-LoveM[M-3]) && 909 abs(LoveM[M-2]-LoveM[M-3]) > abs(LoveM[M-3]-LoveM[M-4]) ){ 910 Lovet[d*nt+t]=LoveM[M-3]; 911 return; 912 } 913 } 914 } 915 Lovet[d*nt+t]=LoveM[NTit-1]; 916 }/*}}}*/ 917 void love_freq_to_temporal(IssmDouble* LoveHt,IssmDouble* LoveLt,IssmDouble* LoveKt,IssmDouble* LoveHf,IssmDouble* LoveLf,IssmDouble* LoveKf, FemModel* femmodel){ /*{{{*/ 939 940 }/*}}}*/ 941 template <typename doubletype> void love_freq_to_temporal(doubletype* LoveHt,doubletype* LoveLt,doubletype* LoveKt,doubletype* LoveHf,doubletype* LoveLf,doubletype* LoveKf, FemModel* femmodel){ /*{{{*/ 918 942 //Transforms all frequency-dependent love numbers into time-dependent love numbers 919 943 int nfreq,sh_nmax,sh_nmin,indxi,indf, NTit; 920 IssmDouble meanh,meanl,meank,dh,dl,dk;921 944 922 945 femmodel->parameters->FindParam(&nfreq,LoveNfreqEnum); … … 924 947 femmodel->parameters->FindParam(&sh_nmin,LoveShNminEnum); 925 948 femmodel->parameters->FindParam(&NTit,LoveNTemporalIterationsEnum); 926 949 927 950 int nt=nfreq/2/NTit; 928 IssmDouble* xi=postwidder_coef(NTit);951 doubletype* xi=postwidder_coef<doubletype>(NTit); 929 952 930 953 for (int d=sh_nmin;d<sh_nmax+1;d++){ 931 954 for (int t=0;t<nt;t++){ 932 postwidder_transform(LoveHt,LoveHf,d,t,NTit,xi,femmodel); 933 postwidder_transform(LoveLt,LoveLf,d,t,NTit,xi,femmodel); 934 postwidder_transform(LoveKt,LoveKf,d,t,NTit,xi,femmodel); 935 } 936 } 937 xDelete<IssmDouble>(xi); 938 }/*}}}*/ 939 void love_core(FemModel* femmodel){ /*{{{*/ 955 postwidder_transform<doubletype>(LoveHt,LoveHf,d,t,NTit,xi,femmodel); 956 postwidder_transform<doubletype>(LoveLt,LoveLf,d,t,NTit,xi,femmodel); 957 postwidder_transform<doubletype>(LoveKt,LoveKf,d,t,NTit,xi,femmodel); 958 } 959 } 960 xDelete<doubletype>(xi); 961 }/*}}}*/ 962 963 /*templated cores:*/ 964 LoveVariables* love_init(FemModel* femmodel, Matlitho* matlitho){/*{{{*/ 965 966 /*initialize Planet_Mass(r) for efficient computation of gravity, value of surface gravity and inital size of the yi equation system*/ 967 968 bool verbosemod = (int)VerboseModule(); 969 int numlayers = matlitho->numlayers; 970 IssmDouble* r = matlitho->radius; 971 IssmDouble r1,r2,ro, GG; 972 973 /*outputs:*/ 974 IssmDouble* EarthMass=NULL; 975 IssmDouble g0,r0; 976 int nyi,starting_layer; 977 978 femmodel->parameters->FindParam(&GG,LoveGravitationalConstantEnum); 979 EarthMass=xNewZeroInit<IssmDouble>(numlayers+1); 980 981 for (int i=0;i<numlayers;i++){ 982 r2 = r[i+1]; 983 ro = matlitho->density[i]; 984 if (i==0){ 985 EarthMass[i] = ro*pow(r2,3.0)*4.0*PI/3.0; 986 }else{ 987 r1=r[i]; 988 EarthMass[i] = EarthMass[i-1] + ro*(pow(r2,3.0)-pow(r1,3.0))*4.0*PI/3.0;; 989 } 990 } 991 992 g0=EarthMass[numlayers-1]*GG/pow(r[numlayers],2.0); 993 r0=r[numlayers]; 994 nyi=6*(numlayers+1); 995 starting_layer=0; 996 997 return new LoveVariables(EarthMass,g0,r0,nyi,starting_layer); 998 999 } /*}}}*/ 1000 template <typename doubletype> void love_core_template(FemModel* femmodel){ /*{{{*/ 1001 1002 Matlitho* matlitho=NULL; 1003 int nfreq,nyi,starting_layer,nstep,forcing_type,dummy; 1004 int sh_nmin,sh_nmax,kernel_index,deleted_layer_offset; 1005 bool allow_layer_deletion,love_kernels, istemporal; 1006 bool verbosemod = (int)VerboseModule(); 1007 IssmDouble g0,r0,mu0, underflow_tol; 1008 IssmDouble *frequencies = NULL; 1009 bool save_results; 1010 bool complex_computation; 1011 1012 doubletype omega; 1013 doubletype lovek, loveh, lovel, loveratio; 1014 1015 doubletype* LoveKf = NULL; 1016 doubletype* LoveHf = NULL; 1017 doubletype* LoveLf = NULL; 1018 doubletype* LoveKernels= NULL; 1019 LoveVariables* vars=NULL; 1020 doubletype* yi_prefactor=NULL; 1021 doubletype* yi_righthandside=NULL; 1022 doubletype* yi=NULL; 1023 1024 if(VerboseSolution()) _printf0_(" computing LOVE numbers\n"); 940 1025 941 1026 /*recover materials parameters: there is only one Matlitho, chase it down the hard way:*/ 942 Matlitho* matlitho=NULL;943 1027 for (Object* & object: femmodel->materials->objects){ 944 1028 Material* material=xDynamicCast<Material*>(object); … … 950 1034 _assert_(matlitho); 951 1035 952 /*love parameters: */ 953 int nfreq,nyi,starting_layer,nstep,forcing_type,dummy; 954 int sh_nmin,sh_nmax,kernel_index,deleted_layer_offset; 955 bool allow_layer_deletion,love_kernels, istemporal; 956 bool verbosemod = (int)VerboseModule(); 957 IssmDouble lovek, loveh, lovel, loveratio; 958 IssmDouble g0,r0,mu0, underflow_tol, omega; 959 IssmDouble *frequencies = NULL; 960 961 /*parameters: */ 962 bool save_results; 963 964 if(VerboseSolution()) _printf0_(" computing LOVE numbers\n"); 965 966 /*Recover some parameters: */ 1036 /*recover parameters: */ 967 1037 femmodel->parameters->FindParam(&save_results,SaveResultsEnum); 968 969 /*recover love number parameters: */970 971 1038 femmodel->parameters->FindParam(&nfreq,LoveNfreqEnum); 972 1039 femmodel->parameters->FindParam(&frequencies,&dummy,LoveFrequenciesEnum); _assert_(nfreq==dummy); … … 981 1048 femmodel->parameters->FindParam(&istemporal,LoveIsTemporalEnum); 982 1049 femmodel->parameters->FindParam(&nstep,LoveIntStepsPerLayerEnum); 1050 femmodel->parameters->FindParam(&complex_computation,LoveComplexComputationEnum); 1051 983 1052 984 1053 /*Initialize three love matrices: geoid, vertical and horizontal displacement (real and imaginary parts) */ 985 IssmDouble* LoveKf = xNewZeroInit<IssmDouble>(nfreq*(sh_nmax+1));986 IssmDouble* LoveHf = xNewZeroInit<IssmDouble>(nfreq*(sh_nmax+1));987 IssmDouble* LoveLf = xNewZeroInit<IssmDouble>(nfreq*(sh_nmax+1));1054 LoveKf = xNewZeroInit<doubletype>(nfreq*(sh_nmax+1)); 1055 LoveHf = xNewZeroInit<doubletype>(nfreq*(sh_nmax+1)); 1056 LoveLf = xNewZeroInit<doubletype>(nfreq*(sh_nmax+1)); 988 1057 989 1058 /*Initialize love kernels (real and imaginary parts): */ 990 IssmDouble* LoveKernelsReal = xNewZeroInit<IssmDouble>(nfreq*(sh_nmax+1)*(matlitho->numlayers+1)*6); 991 IssmDouble* LoveKernelsImag = xNewZeroInit<IssmDouble>(nfreq*(sh_nmax+1)*(matlitho->numlayers+1)*6); 992 993 love_init(femmodel,matlitho); 994 femmodel->parameters->FindParam(&nyi,LoveNYiEquationsEnum); 995 femmodel->parameters->FindParam(&starting_layer,LoveStartingLayerEnum); 996 IssmDouble* yi_prefactor=xNewZeroInit<IssmDouble>(6*6*nstep*matlitho->numlayers); 997 IssmDouble* yi_righthandside=xNewZeroInit<IssmDouble>(nyi); 998 IssmDouble* yi=xNewZeroInit<IssmDouble>(nyi*nyi); 1059 LoveKernels= xNewZeroInit<doubletype>(nfreq*(sh_nmax+1)*(matlitho->numlayers+1)*6); 1060 1061 vars=love_init(femmodel,matlitho); 1062 1063 yi_prefactor=xNewZeroInit<doubletype>(6*6*nstep*matlitho->numlayers); 1064 yi_righthandside=xNewZeroInit<doubletype>(vars->nyi); 1065 yi=xNewZeroInit<doubletype>(vars->nyi*vars->nyi); 999 1066 1000 1067 //precalculate yi coefficients that do not depend on degree or frequency 1001 fill_yi_prefactor (yi_prefactor, NULL, NULL,femmodel, matlitho);1068 fill_yi_prefactor<doubletype>(yi_prefactor, NULL, NULL,femmodel, matlitho,vars); 1002 1069 for(int deg=sh_nmin;deg<sh_nmax+1;deg++){ 1003 1070 1004 1071 //precalculate yi coefficients that depend on degree but not frequency 1005 fill_yi_prefactor (yi_prefactor, °, NULL,femmodel, matlitho);1072 fill_yi_prefactor<doubletype>(yi_prefactor, °, NULL,femmodel, matlitho,vars); 1006 1073 1007 1074 for (int fr=0;fr<nfreq;fr++){ 1008 omega= 2.0*PI*frequencies[fr]; //angular frequency1075 omega=angular_frequency<doubletype>(frequencies[fr]); 1009 1076 1010 1077 //precalculate yi coefficients that depend on degree and frequency 1011 fill_yi_prefactor (yi_prefactor, °,&omega,femmodel, matlitho);1012 1013 yi_boundary_conditions (yi_righthandside,deg,femmodel,matlitho);1014 1015 build_yi_system (yi,deg,omega,yi_prefactor,femmodel,matlitho);1016 1017 solve_yi_system (&loveh,&lovel,&lovek, deg, omega, yi, yi_righthandside,femmodel, matlitho);1078 fill_yi_prefactor<doubletype>(yi_prefactor, °,&omega,femmodel, matlitho,vars); 1079 1080 yi_boundary_conditions<doubletype>(yi_righthandside,deg,femmodel,matlitho,vars); 1081 1082 build_yi_system<doubletype>(yi,deg,omega,yi_prefactor,femmodel,matlitho,vars); 1083 1084 solve_yi_system<doubletype>(&loveh,&lovel,&lovek, deg, omega, yi, yi_righthandside,femmodel, matlitho,vars); 1018 1085 1019 1086 LoveHf[deg*nfreq+fr]=loveh; … … 1021 1088 LoveLf[deg*nfreq+fr]=lovel; 1022 1089 1023 femmodel->parameters->FindParam(&nyi,LoveNYiEquationsEnum); //synchronize nyi in case we deleted a layer 1024 deleted_layer_offset=(matlitho->numlayers+1)*6-nyi;// =6 per deleted layer 1025 kernel_index=deg*nfreq*(matlitho->numlayers+1)*6 + 1026 fr*(matlitho->numlayers+1)*6 + 1027 deleted_layer_offset; 1028 for (int i=0;i<nyi;i++){ 1029 LoveKernelsReal[kernel_index+i]=yi_righthandside[i]; 1030 } 1031 } 1032 } 1033 1034 1035 xDelete<IssmDouble>(yi); 1036 xDelete<IssmDouble>(yi_righthandside); 1090 deleted_layer_offset=(matlitho->numlayers+1)*6-vars->nyi;// =6 per deleted layer 1091 kernel_index=deg*nfreq*(matlitho->numlayers+1)*6 + fr*(matlitho->numlayers+1)*6 + deleted_layer_offset; 1092 for (int i=0;i<vars->nyi;i++){ 1093 LoveKernels[kernel_index+i]=yi_righthandside[i]; 1094 } 1095 } 1096 } 1097 1098 1099 xDelete<doubletype>(yi); 1100 xDelete<doubletype>(yi_righthandside); 1037 1101 1038 1102 1039 1103 //Temporal love numbers 1040 if (istemporal ){1104 if (istemporal && !complex_computation){ 1041 1105 int NTit; 1042 1106 femmodel->parameters->FindParam(&NTit,LoveNTemporalIterationsEnum); 1043 1107 int nt = nfreq/2/NTit; 1044 1108 1045 IssmDouble* LoveHt=xNewZeroInit<IssmDouble>((sh_nmax+1)*nt);1046 IssmDouble* LoveLt=xNewZeroInit<IssmDouble>((sh_nmax+1)*nt);1047 IssmDouble* LoveKt=xNewZeroInit<IssmDouble>((sh_nmax+1)*nt);1048 1049 love_freq_to_temporal (LoveHt,LoveLt,LoveKt,LoveHf,LoveLf,LoveKf,femmodel);1050 1051 femmodel->results->AddObject(new GenericExternalResult< IssmDouble*>(femmodel->results->Size()+1,LoveKrEnum,LoveKt,sh_nmax+1,nt,0,0));1052 femmodel->results->AddObject(new GenericExternalResult< IssmDouble*>(femmodel->results->Size()+1,LoveHrEnum,LoveHt,sh_nmax+1,nt,0,0));1053 femmodel->results->AddObject(new GenericExternalResult< IssmDouble*>(femmodel->results->Size()+1,LoveLrEnum,LoveLt,sh_nmax+1,nt,0,0));1054 1055 xDelete< IssmDouble>(LoveHt);1056 xDelete< IssmDouble>(LoveLt);1057 xDelete< IssmDouble>(LoveKt);1058 } 1059 1060 femmodel->results->AddObject(new GenericExternalResult< IssmDouble*>(femmodel->results->Size()+1,LoveKiEnum,LoveKf,sh_nmax+1,nfreq,0,0));1061 femmodel->results->AddObject(new GenericExternalResult< IssmDouble*>(femmodel->results->Size()+1,LoveHiEnum,LoveHf,sh_nmax+1,nfreq,0,0));1062 femmodel->results->AddObject(new GenericExternalResult< IssmDouble*>(femmodel->results->Size()+1,LoveLiEnum,LoveLf,sh_nmax+1,nfreq,0,0));1109 doubletype* LoveHt=xNewZeroInit<doubletype>((sh_nmax+1)*nt); 1110 doubletype* LoveLt=xNewZeroInit<doubletype>((sh_nmax+1)*nt); 1111 doubletype* LoveKt=xNewZeroInit<doubletype>((sh_nmax+1)*nt); 1112 1113 love_freq_to_temporal<doubletype>(LoveHt,LoveLt,LoveKt,LoveHf,LoveLf,LoveKf,femmodel); 1114 1115 femmodel->results->AddObject(new GenericExternalResult<doubletype*>(femmodel->results->Size()+1,LoveKrEnum,LoveKt,sh_nmax+1,nt,0,0)); 1116 femmodel->results->AddObject(new GenericExternalResult<doubletype*>(femmodel->results->Size()+1,LoveHrEnum,LoveHt,sh_nmax+1,nt,0,0)); 1117 femmodel->results->AddObject(new GenericExternalResult<doubletype*>(femmodel->results->Size()+1,LoveLrEnum,LoveLt,sh_nmax+1,nt,0,0)); 1118 1119 xDelete<doubletype>(LoveHt); 1120 xDelete<doubletype>(LoveLt); 1121 xDelete<doubletype>(LoveKt); 1122 } 1123 1124 femmodel->results->AddObject(new GenericExternalResult<doubletype*>(femmodel->results->Size()+1,LoveKiEnum,LoveKf,sh_nmax+1,nfreq,0,0)); 1125 femmodel->results->AddObject(new GenericExternalResult<doubletype*>(femmodel->results->Size()+1,LoveHiEnum,LoveHf,sh_nmax+1,nfreq,0,0)); 1126 femmodel->results->AddObject(new GenericExternalResult<doubletype*>(femmodel->results->Size()+1,LoveLiEnum,LoveLf,sh_nmax+1,nfreq,0,0)); 1063 1127 1064 1128 … … 1082 1146 /*Only when love_kernels is on*/ 1083 1147 if (love_kernels==1) { 1084 femmodel->results->AddObject(new GenericExternalResult< IssmDouble*>(femmodel->results->Size()+1,LoveKernelsRealEnum,LoveKernelsReal,(sh_nmax+1)*(matlitho->numlayers+1)*6,nfreq,0,0));1148 femmodel->results->AddObject(new GenericExternalResult<doubletype*>(femmodel->results->Size()+1,LoveKernelsEnum,LoveKernels,(sh_nmax+1)*(matlitho->numlayers+1)*6,nfreq,0,0)); 1085 1149 //femmodel->results->AddObject(new GenericExternalResult<IssmDouble*>(femmodel->results->Size()+1,LoveKernelsImagEnum,LoveKernelsImag,(sh_nmax+1)*(matlitho->numlayers+1)*6,nfreq,0,0)); 1086 1150 } … … 1088 1152 /*Free resources:*/ 1089 1153 xDelete<IssmDouble>(frequencies); 1090 xDelete<IssmDouble>(LoveKf); 1091 xDelete<IssmDouble>(LoveHf); 1092 xDelete<IssmDouble>(LoveLf); 1093 //xDelete<IssmDouble>(LoveKi); 1094 //xDelete<IssmDouble>(LoveHi); 1154 xDelete<doubletype>(LoveKf); 1155 xDelete<doubletype>(LoveHf); 1156 xDelete<doubletype>(LoveLf); 1095 1157 //xDelete<IssmDouble>(LoveLi); 1096 xDelete<IssmDouble>(LoveKernelsReal); 1097 xDelete<IssmDouble>(LoveKernelsImag); 1158 xDelete<doubletype>(LoveKernels); 1098 1159 } /*}}}*/ 1160 1161 /*cores and template instantiations:*/ 1162 /*template instantiations :{{{*/ 1163 template void love_core_template<IssmDouble>(FemModel* femmodel); 1164 template void love_core_template<IssmComplex>(FemModel* femmodel); 1165 template void fill_yi_prefactor<IssmDouble>(IssmDouble* yi_prefactor, int* pdeg, IssmDouble* pomega, FemModel* femmodel, Matlitho* matlitho, LoveVariables* vars); 1166 template void fill_yi_prefactor<IssmComplex>(IssmComplex* yi_prefactor, int* pdeg, IssmComplex* pomega, FemModel* femmodel, Matlitho* matlitho, LoveVariables* vars); 1167 template void GetEarthRheology<IssmDouble>(IssmDouble* pla, IssmDouble* pmu, int layer_index, IssmDouble omega, Matlitho* matlitho); 1168 template void GetEarthRheology<IssmComplex>(IssmComplex* pla, IssmComplex* pmu, int layer_index, IssmComplex omega, Matlitho* matlitho); 1169 template void yi_boundary_conditions<IssmDouble>(IssmDouble* yi_righthandside, int deg, FemModel* femmodel, Matlitho* matlitho,LoveVariables* vars); 1170 template void yi_boundary_conditions<IssmComplex>(IssmComplex* yi_righthandside, int deg, FemModel* femmodel, Matlitho* matlitho,LoveVariables* vars); 1171 template void yi_derivatives<IssmDouble>(IssmDouble* dydx, IssmDouble* y, int layer_index, int n, IssmDouble* yi_prefactor, FemModel* femmodel, Matlitho* matlitho); 1172 template void yi_derivatives<IssmComplex>(IssmComplex* dydx, IssmComplex* y, int layer_index, int n, IssmComplex* yi_prefactor, FemModel* femmodel, Matlitho* matlitho); 1173 template void propagate_yi_RK2<IssmDouble>(IssmDouble* y, IssmDouble xmin, IssmDouble xmax, int layer_index, IssmDouble* yi_prefactor, FemModel* femmodel, Matlitho* matlitho); 1174 template void propagate_yi_RK2<IssmComplex>(IssmComplex* y, IssmDouble xmin, IssmDouble xmax, int layer_index, IssmComplex* yi_prefactor, FemModel* femmodel, Matlitho* matlitho); 1175 template void Innersphere_boundaryconditions<IssmDouble>(IssmDouble* yi, int layer_index, int deg, IssmDouble omega, FemModel* femmodel, Matlitho* matlitho, LoveVariables* vars); 1176 template void Innersphere_boundaryconditions<IssmComplex>(IssmComplex* yi, int layer_index, int deg, IssmComplex omega, FemModel* femmodel, Matlitho* matlitho, LoveVariables* vars); 1177 template void build_yi_system<IssmDouble>(IssmDouble* yi, int deg, IssmDouble omega, IssmDouble* yi_prefactor, FemModel* femmodel, Matlitho* matlitho,LoveVariables* vars); 1178 template void build_yi_system<IssmComplex>(IssmComplex* yi, int deg, IssmComplex omega, IssmComplex* yi_prefactor, FemModel* femmodel, Matlitho* matlitho,LoveVariables* vars); 1179 template void solve_yi_system<IssmDouble>(IssmDouble* loveh, IssmDouble* lovel, IssmDouble* lovek, int deg, IssmDouble omega, IssmDouble* yi, IssmDouble* rhs, FemModel* femmodel, Matlitho* matlitho, LoveVariables* vars); 1180 template void solve_yi_system<IssmComplex>(IssmComplex* loveh, IssmComplex* lovel, IssmComplex* lovek, int deg, IssmComplex omega, IssmComplex* yi, IssmComplex* rhs, FemModel* femmodel, Matlitho* matlitho, LoveVariables* vars); 1181 template IssmDouble factorial<IssmDouble>(int n); 1182 template IssmDouble* postwidder_coef<IssmDouble>(int NTit); 1183 template IssmDouble n_C_r<IssmDouble>(int n, int r); 1184 template void postwidder_transform<IssmDouble>(IssmDouble* Lovet, IssmDouble* Lovef,int d, int t, int NTit, IssmDouble* xi, FemModel* femmodel); 1185 1186 /*}}}*/ 1187 void love_core(FemModel* femmodel){ /*{{{*/ 1188 1189 bool complex_computation; 1190 1191 femmodel->parameters->FindParam(&complex_computation,LoveComplexComputationEnum); 1192 1193 if(complex_computation) love_core_template<IssmComplex>(femmodel); 1194 else love_core_template<IssmDouble>(femmodel); 1195 1196 } /*}}}*/ -
issm/trunk-jpl/src/c/shared/Enum/Enum.vim
r26222 r26242 256 256 syn keyword cConstant LockFileNameEnum 257 257 syn keyword cConstant LoveAllowLayerDeletionEnum 258 syn keyword cConstant LoveCoreMantleBoundaryEnum 259 syn keyword cConstant LoveEarthMassEnum 258 260 syn keyword cConstant LoveForcingTypeEnum 259 261 syn keyword cConstant LoveFrequenciesEnum 262 syn keyword cConstant LoveIsTemporalEnum 260 263 syn keyword cConstant LoveG0Enum 264 syn keyword cConstant LoveGravitationalConstantEnum 265 syn keyword cConstant LoveInnerCoreBoundaryEnum 266 syn keyword cConstant LoveComplexComputationEnum 267 syn keyword cConstant LoveIntStepsPerLayerEnum 261 268 syn keyword cConstant LoveKernelsEnum 262 269 syn keyword cConstant LoveMu0Enum 263 270 syn keyword cConstant LoveNfreqEnum 271 syn keyword cConstant LoveNTemporalIterationsEnum 272 syn keyword cConstant LoveNYiEquationsEnum 264 273 syn keyword cConstant LoveR0Enum 265 274 syn keyword cConstant LoveShNmaxEnum 266 275 syn keyword cConstant LoveShNminEnum 276 syn keyword cConstant LoveStartingLayerEnum 277 syn keyword cConstant LoveUnderflowTolEnum 267 278 syn keyword cConstant MassFluxSegmentsEnum 268 279 syn keyword cConstant MassFluxSegmentsPresentEnum … … 783 794 syn keyword cConstant SealevelGrotm2Enum 784 795 syn keyword cConstant SealevelGrotm3Enum 796 syn keyword cConstant SealevelGUrotm1Enum 797 syn keyword cConstant SealevelGUrotm2Enum 798 syn keyword cConstant SealevelGUrotm3Enum 799 syn keyword cConstant SealevelGNrotm1Enum 800 syn keyword cConstant SealevelGNrotm2Enum 801 syn keyword cConstant SealevelGNrotm3Enum 802 syn keyword cConstant SealevelGErotm1Enum 803 syn keyword cConstant SealevelGErotm2Enum 804 syn keyword cConstant SealevelGErotm3Enum 785 805 syn keyword cConstant SealevelRSLBarystaticEnum 786 806 syn keyword cConstant SealevelRSLRateEnum … … 1528 1548 syn keyword cType GenericParam 1529 1549 syn keyword cType GiaDeflectionCoreArgs 1550 syn keyword cType GrdLoads 1530 1551 syn keyword cType Hook 1531 1552 syn keyword cType Input -
issm/trunk-jpl/src/c/shared/Enum/EnumDefinitions.h
r26233 r26242 258 258 LoveGravitationalConstantEnum, 259 259 LoveInnerCoreBoundaryEnum, 260 LoveComplexComputationEnum, 260 261 LoveIntStepsPerLayerEnum, 261 262 LoveKernelsEnum, -
issm/trunk-jpl/src/c/shared/Enum/EnumToStringx.cpp
r26222 r26242 258 258 case LockFileNameEnum : return "LockFileName"; 259 259 case LoveAllowLayerDeletionEnum : return "LoveAllowLayerDeletion"; 260 case LoveCoreMantleBoundaryEnum : return "LoveCoreMantleBoundary"; 261 case LoveEarthMassEnum : return "LoveEarthMass"; 260 262 case LoveForcingTypeEnum : return "LoveForcingType"; 261 263 case LoveFrequenciesEnum : return "LoveFrequencies"; 264 case LoveIsTemporalEnum : return "LoveIsTemporal"; 262 265 case LoveG0Enum : return "LoveG0"; 266 case LoveGravitationalConstantEnum : return "LoveGravitationalConstant"; 267 case LoveInnerCoreBoundaryEnum : return "LoveInnerCoreBoundary"; 268 case LoveComplexComputationEnum : return "LoveComplexComputation"; 269 case LoveIntStepsPerLayerEnum : return "LoveIntStepsPerLayer"; 263 270 case LoveKernelsEnum : return "LoveKernels"; 264 271 case LoveMu0Enum : return "LoveMu0"; 265 272 case LoveNfreqEnum : return "LoveNfreq"; 273 case LoveNTemporalIterationsEnum : return "LoveNTemporalIterations"; 274 case LoveNYiEquationsEnum : return "LoveNYiEquations"; 266 275 case LoveR0Enum : return "LoveR0"; 267 276 case LoveShNmaxEnum : return "LoveShNmax"; 268 277 case LoveShNminEnum : return "LoveShNmin"; 278 case LoveStartingLayerEnum : return "LoveStartingLayer"; 279 case LoveUnderflowTolEnum : return "LoveUnderflowTol"; 269 280 case MassFluxSegmentsEnum : return "MassFluxSegments"; 270 281 case MassFluxSegmentsPresentEnum : return "MassFluxSegmentsPresent"; … … 785 796 case SealevelGrotm2Enum : return "SealevelGrotm2"; 786 797 case SealevelGrotm3Enum : return "SealevelGrotm3"; 798 case SealevelGUrotm1Enum : return "SealevelGUrotm1"; 799 case SealevelGUrotm2Enum : return "SealevelGUrotm2"; 800 case SealevelGUrotm3Enum : return "SealevelGUrotm3"; 801 case SealevelGNrotm1Enum : return "SealevelGNrotm1"; 802 case SealevelGNrotm2Enum : return "SealevelGNrotm2"; 803 case SealevelGNrotm3Enum : return "SealevelGNrotm3"; 804 case SealevelGErotm1Enum : return "SealevelGErotm1"; 805 case SealevelGErotm2Enum : return "SealevelGErotm2"; 806 case SealevelGErotm3Enum : return "SealevelGErotm3"; 787 807 case SealevelRSLBarystaticEnum : return "SealevelRSLBarystatic"; 788 808 case SealevelRSLRateEnum : return "SealevelRSLRate"; -
issm/trunk-jpl/src/c/shared/Enum/StringToEnumx.cpp
r26222 r26242 264 264 if(stage==3){ 265 265 if (strcmp(name,"LoveAllowLayerDeletion")==0) return LoveAllowLayerDeletionEnum; 266 else if (strcmp(name,"LoveCoreMantleBoundary")==0) return LoveCoreMantleBoundaryEnum; 267 else if (strcmp(name,"LoveEarthMass")==0) return LoveEarthMassEnum; 266 268 else if (strcmp(name,"LoveForcingType")==0) return LoveForcingTypeEnum; 267 269 else if (strcmp(name,"LoveFrequencies")==0) return LoveFrequenciesEnum; 270 else if (strcmp(name,"LoveIsTemporal")==0) return LoveIsTemporalEnum; 268 271 else if (strcmp(name,"LoveG0")==0) return LoveG0Enum; 272 else if (strcmp(name,"LoveGravitationalConstant")==0) return LoveGravitationalConstantEnum; 273 else if (strcmp(name,"LoveInnerCoreBoundary")==0) return LoveInnerCoreBoundaryEnum; 274 else if (strcmp(name,"LoveComplexComputation")==0) return LoveComplexComputationEnum; 275 else if (strcmp(name,"LoveIntStepsPerLayer")==0) return LoveIntStepsPerLayerEnum; 269 276 else if (strcmp(name,"LoveKernels")==0) return LoveKernelsEnum; 270 277 else if (strcmp(name,"LoveMu0")==0) return LoveMu0Enum; 271 278 else if (strcmp(name,"LoveNfreq")==0) return LoveNfreqEnum; 279 else if (strcmp(name,"LoveNTemporalIterations")==0) return LoveNTemporalIterationsEnum; 280 else if (strcmp(name,"LoveNYiEquations")==0) return LoveNYiEquationsEnum; 272 281 else if (strcmp(name,"LoveR0")==0) return LoveR0Enum; 273 282 else if (strcmp(name,"LoveShNmax")==0) return LoveShNmaxEnum; 274 283 else if (strcmp(name,"LoveShNmin")==0) return LoveShNminEnum; 284 else if (strcmp(name,"LoveStartingLayer")==0) return LoveStartingLayerEnum; 285 else if (strcmp(name,"LoveUnderflowTol")==0) return LoveUnderflowTolEnum; 275 286 else if (strcmp(name,"MassFluxSegments")==0) return MassFluxSegmentsEnum; 276 287 else if (strcmp(name,"MassFluxSegmentsPresent")==0) return MassFluxSegmentsPresentEnum; … … 372 383 else if (strcmp(name,"SealevelchangeGRigid")==0) return SealevelchangeGRigidEnum; 373 384 else if (strcmp(name,"SealevelchangeGElastic")==0) return SealevelchangeGElasticEnum; 374 else if (strcmp(name,"SolidearthSettingsComputesealevelchange")==0) return SolidearthSettingsComputesealevelchangeEnum; 385 else stage=4; 386 } 387 if(stage==4){ 388 if (strcmp(name,"SolidearthSettingsComputesealevelchange")==0) return SolidearthSettingsComputesealevelchangeEnum; 375 389 else if (strcmp(name,"SolidearthSettingsGRD")==0) return SolidearthSettingsGRDEnum; 376 390 else if (strcmp(name,"SolidearthSettingsRunFrequency")==0) return SolidearthSettingsRunFrequencyEnum; … … 383 397 else if (strcmp(name,"SealevelchangeRequestedOutputs")==0) return SealevelchangeRequestedOutputsEnum; 384 398 else if (strcmp(name,"SolidearthSettingsRigid")==0) return SolidearthSettingsRigidEnum; 385 else stage=4; 386 } 387 if(stage==4){ 388 if (strcmp(name,"SolidearthSettingsRotation")==0) return SolidearthSettingsRotationEnum; 399 else if (strcmp(name,"SolidearthSettingsRotation")==0) return SolidearthSettingsRotationEnum; 389 400 else if (strcmp(name,"SealevelchangeRunCount")==0) return SealevelchangeRunCountEnum; 390 401 else if (strcmp(name,"SealevelchangeTransitions")==0) return SealevelchangeTransitionsEnum; … … 495 506 else if (strcmp(name,"TimesteppingType")==0) return TimesteppingTypeEnum; 496 507 else if (strcmp(name,"ToMITgcmComm")==0) return ToMITgcmCommEnum; 497 else if (strcmp(name,"ToolkitsFileName")==0) return ToolkitsFileNameEnum; 508 else stage=5; 509 } 510 if(stage==5){ 511 if (strcmp(name,"ToolkitsFileName")==0) return ToolkitsFileNameEnum; 498 512 else if (strcmp(name,"ToolkitsOptionsAnalyses")==0) return ToolkitsOptionsAnalysesEnum; 499 513 else if (strcmp(name,"ToolkitsOptionsStrings")==0) return ToolkitsOptionsStringsEnum; … … 506 520 else if (strcmp(name,"TransientIshydrology")==0) return TransientIshydrologyEnum; 507 521 else if (strcmp(name,"TransientIsmasstransport")==0) return TransientIsmasstransportEnum; 508 else stage=5; 509 } 510 if(stage==5){ 511 if (strcmp(name,"TransientIsoceantransport")==0) return TransientIsoceantransportEnum; 522 else if (strcmp(name,"TransientIsoceantransport")==0) return TransientIsoceantransportEnum; 512 523 else if (strcmp(name,"TransientIsmovingfront")==0) return TransientIsmovingfrontEnum; 513 524 else if (strcmp(name,"TransientIsoceancoupling")==0) return TransientIsoceancouplingEnum; … … 618 629 else if (strcmp(name,"DistanceToCalvingfront")==0) return DistanceToCalvingfrontEnum; 619 630 else if (strcmp(name,"DistanceToGroundingline")==0) return DistanceToGroundinglineEnum; 620 else if (strcmp(name,"Domain2Dhorizontal")==0) return Domain2DhorizontalEnum; 631 else stage=6; 632 } 633 if(stage==6){ 634 if (strcmp(name,"Domain2Dhorizontal")==0) return Domain2DhorizontalEnum; 621 635 else if (strcmp(name,"Domain2Dvertical")==0) return Domain2DverticalEnum; 622 636 else if (strcmp(name,"Domain3D")==0) return Domain3DEnum; … … 629 643 else if (strcmp(name,"EffectivePressureTransient")==0) return EffectivePressureTransientEnum; 630 644 else if (strcmp(name,"Enthalpy")==0) return EnthalpyEnum; 631 else stage=6; 632 } 633 if(stage==6){ 634 if (strcmp(name,"EnthalpyPicard")==0) return EnthalpyPicardEnum; 645 else if (strcmp(name,"EnthalpyPicard")==0) return EnthalpyPicardEnum; 635 646 else if (strcmp(name,"EplHead")==0) return EplHeadEnum; 636 647 else if (strcmp(name,"EplHeadOld")==0) return EplHeadOldEnum; … … 741 752 else if (strcmp(name,"Neumannflux")==0) return NeumannfluxEnum; 742 753 else if (strcmp(name,"NewDamage")==0) return NewDamageEnum; 743 else if (strcmp(name,"Node")==0) return NodeEnum; 754 else stage=7; 755 } 756 if(stage==7){ 757 if (strcmp(name,"Node")==0) return NodeEnum; 744 758 else if (strcmp(name,"OmegaAbsGradient")==0) return OmegaAbsGradientEnum; 745 759 else if (strcmp(name,"OceantransportSpcbottompressure")==0) return OceantransportSpcbottompressureEnum; … … 752 766 else if (strcmp(name,"Radar")==0) return RadarEnum; 753 767 else if (strcmp(name,"RadarAttenuationMacGregor")==0) return RadarAttenuationMacGregorEnum; 754 else stage=7; 755 } 756 if(stage==7){ 757 if (strcmp(name,"RadarAttenuationWolff")==0) return RadarAttenuationWolffEnum; 768 else if (strcmp(name,"RadarAttenuationWolff")==0) return RadarAttenuationWolffEnum; 758 769 else if (strcmp(name,"RadarIcePeriod")==0) return RadarIcePeriodEnum; 759 770 else if (strcmp(name,"RadarPowerMacGregor")==0) return RadarPowerMacGregorEnum; … … 803 814 else if (strcmp(name,"SealevelGrotm2")==0) return SealevelGrotm2Enum; 804 815 else if (strcmp(name,"SealevelGrotm3")==0) return SealevelGrotm3Enum; 816 else if (strcmp(name,"SealevelGUrotm1")==0) return SealevelGUrotm1Enum; 817 else if (strcmp(name,"SealevelGUrotm2")==0) return SealevelGUrotm2Enum; 818 else if (strcmp(name,"SealevelGUrotm3")==0) return SealevelGUrotm3Enum; 819 else if (strcmp(name,"SealevelGNrotm1")==0) return SealevelGNrotm1Enum; 820 else if (strcmp(name,"SealevelGNrotm2")==0) return SealevelGNrotm2Enum; 821 else if (strcmp(name,"SealevelGNrotm3")==0) return SealevelGNrotm3Enum; 822 else if (strcmp(name,"SealevelGErotm1")==0) return SealevelGErotm1Enum; 823 else if (strcmp(name,"SealevelGErotm2")==0) return SealevelGErotm2Enum; 824 else if (strcmp(name,"SealevelGErotm3")==0) return SealevelGErotm3Enum; 805 825 else if (strcmp(name,"SealevelRSLBarystatic")==0) return SealevelRSLBarystaticEnum; 806 826 else if (strcmp(name,"SealevelRSLRate")==0) return SealevelRSLRateEnum; … … 855 875 else if (strcmp(name,"SmbD")==0) return SmbDEnum; 856 876 else if (strcmp(name,"SmbDailyairdensity")==0) return SmbDailyairdensityEnum; 857 else if (strcmp(name,"SmbDailyairhumidity")==0) return SmbDailyairhumidityEnum; 877 else stage=8; 878 } 879 if(stage==8){ 880 if (strcmp(name,"SmbDailyairhumidity")==0) return SmbDailyairhumidityEnum; 858 881 else if (strcmp(name,"SmbDailydlradiation")==0) return SmbDailydlradiationEnum; 859 882 else if (strcmp(name,"SmbDailydsradiation")==0) return SmbDailydsradiationEnum; … … 875 898 else if (strcmp(name,"SmbEC")==0) return SmbECEnum; 876 899 else if (strcmp(name,"SmbECDt")==0) return SmbECDtEnum; 877 else stage=8; 878 } 879 if(stage==8){ 880 if (strcmp(name,"SmbECini")==0) return SmbECiniEnum; 900 else if (strcmp(name,"SmbECini")==0) return SmbECiniEnum; 881 901 else if (strcmp(name,"SmbEla")==0) return SmbElaEnum; 882 902 else if (strcmp(name,"SmbEvaporation")==0) return SmbEvaporationEnum; … … 978 998 else if (strcmp(name,"SurfaceSlopeX")==0) return SurfaceSlopeXEnum; 979 999 else if (strcmp(name,"SurfaceSlopeY")==0) return SurfaceSlopeYEnum; 980 else if (strcmp(name,"Temperature")==0) return TemperatureEnum; 1000 else stage=9; 1001 } 1002 if(stage==9){ 1003 if (strcmp(name,"Temperature")==0) return TemperatureEnum; 981 1004 else if (strcmp(name,"TemperaturePDD")==0) return TemperaturePDDEnum; 982 1005 else if (strcmp(name,"TemperaturePicard")==0) return TemperaturePicardEnum; … … 998 1021 else if (strcmp(name,"VxMesh")==0) return VxMeshEnum; 999 1022 else if (strcmp(name,"VxObs")==0) return VxObsEnum; 1000 else stage=9; 1001 } 1002 if(stage==9){ 1003 if (strcmp(name,"VxShear")==0) return VxShearEnum; 1023 else if (strcmp(name,"VxShear")==0) return VxShearEnum; 1004 1024 else if (strcmp(name,"VxSurface")==0) return VxSurfaceEnum; 1005 1025 else if (strcmp(name,"VyAverage")==0) return VyAverageEnum; … … 1101 1121 else if (strcmp(name,"Outputdefinition78")==0) return Outputdefinition78Enum; 1102 1122 else if (strcmp(name,"Outputdefinition79")==0) return Outputdefinition79Enum; 1103 else if (strcmp(name,"Outputdefinition7")==0) return Outputdefinition7Enum; 1123 else stage=10; 1124 } 1125 if(stage==10){ 1126 if (strcmp(name,"Outputdefinition7")==0) return Outputdefinition7Enum; 1104 1127 else if (strcmp(name,"Outputdefinition80")==0) return Outputdefinition80Enum; 1105 1128 else if (strcmp(name,"Outputdefinition81")==0) return Outputdefinition81Enum; … … 1121 1144 else if (strcmp(name,"Outputdefinition96")==0) return Outputdefinition96Enum; 1122 1145 else if (strcmp(name,"Outputdefinition97")==0) return Outputdefinition97Enum; 1123 else stage=10; 1124 } 1125 if(stage==10){ 1126 if (strcmp(name,"Outputdefinition98")==0) return Outputdefinition98Enum; 1146 else if (strcmp(name,"Outputdefinition98")==0) return Outputdefinition98Enum; 1127 1147 else if (strcmp(name,"Outputdefinition99")==0) return Outputdefinition99Enum; 1128 1148 else if (strcmp(name,"Outputdefinition9")==0) return Outputdefinition9Enum; … … 1224 1244 else if (strcmp(name,"FileParam")==0) return FileParamEnum; 1225 1245 else if (strcmp(name,"FixedTimestepping")==0) return FixedTimesteppingEnum; 1226 else if (strcmp(name,"FloatingArea")==0) return FloatingAreaEnum; 1246 else stage=11; 1247 } 1248 if(stage==11){ 1249 if (strcmp(name,"FloatingArea")==0) return FloatingAreaEnum; 1227 1250 else if (strcmp(name,"FloatingAreaScaled")==0) return FloatingAreaScaledEnum; 1228 1251 else if (strcmp(name,"FloatingMeltRate")==0) return FloatingMeltRateEnum; … … 1244 1267 else if (strcmp(name,"Gradient1")==0) return Gradient1Enum; 1245 1268 else if (strcmp(name,"Gradient2")==0) return Gradient2Enum; 1246 else stage=11; 1247 } 1248 if(stage==11){ 1249 if (strcmp(name,"Gradient3")==0) return Gradient3Enum; 1269 else if (strcmp(name,"Gradient3")==0) return Gradient3Enum; 1250 1270 else if (strcmp(name,"Gradient4")==0) return Gradient4Enum; 1251 1271 else if (strcmp(name,"GroundedArea")==0) return GroundedAreaEnum; … … 1347 1367 else if (strcmp(name,"MinVy")==0) return MinVyEnum; 1348 1368 else if (strcmp(name,"MinVz")==0) return MinVzEnum; 1349 else if (strcmp(name,"MismipFloatingMeltRate")==0) return MismipFloatingMeltRateEnum; 1369 else stage=12; 1370 } 1371 if(stage==12){ 1372 if (strcmp(name,"MismipFloatingMeltRate")==0) return MismipFloatingMeltRateEnum; 1350 1373 else if (strcmp(name,"Moulin")==0) return MoulinEnum; 1351 1374 else if (strcmp(name,"MpiDense")==0) return MpiDenseEnum; … … 1367 1390 else if (strcmp(name,"OceantransportSolution")==0) return OceantransportSolutionEnum; 1368 1391 else if (strcmp(name,"OldGradient")==0) return OldGradientEnum; 1369 else stage=12; 1370 } 1371 if(stage==12){ 1372 if (strcmp(name,"OneLayerP4z")==0) return OneLayerP4zEnum; 1392 else if (strcmp(name,"OneLayerP4z")==0) return OneLayerP4zEnum; 1373 1393 else if (strcmp(name,"Open")==0) return OpenEnum; 1374 1394 else if (strcmp(name,"Option")==0) return OptionEnum; … … 1470 1490 else if (strcmp(name,"ThicknessErrorEstimator")==0) return ThicknessErrorEstimatorEnum; 1471 1491 else if (strcmp(name,"TotalCalvingFluxLevelset")==0) return TotalCalvingFluxLevelsetEnum; 1472 else if (strcmp(name,"TotalCalvingMeltingFluxLevelset")==0) return TotalCalvingMeltingFluxLevelsetEnum; 1492 else stage=13; 1493 } 1494 if(stage==13){ 1495 if (strcmp(name,"TotalCalvingMeltingFluxLevelset")==0) return TotalCalvingMeltingFluxLevelsetEnum; 1473 1496 else if (strcmp(name,"TotalFloatingBmb")==0) return TotalFloatingBmbEnum; 1474 1497 else if (strcmp(name,"TotalFloatingBmbScaled")==0) return TotalFloatingBmbScaledEnum; … … 1490 1513 else if (strcmp(name,"VertexSId")==0) return VertexSIdEnum; 1491 1514 else if (strcmp(name,"Vertices")==0) return VerticesEnum; 1492 else stage=13; 1493 } 1494 if(stage==13){ 1495 if (strcmp(name,"ViscousHeating")==0) return ViscousHeatingEnum; 1515 else if (strcmp(name,"ViscousHeating")==0) return ViscousHeatingEnum; 1496 1516 else if (strcmp(name,"Water")==0) return WaterEnum; 1497 1517 else if (strcmp(name,"XTaylorHood")==0) return XTaylorHoodEnum; -
issm/trunk-jpl/src/c/shared/Numerics/types.h
r23357 r26242 13 13 14 14 #include <stdio.h> 15 #include <complex> 15 16 16 17 /*here are our abstracted types: inspired on petsc */ … … 24 25 /*ADOLC typedefs*/ 25 26 #include "adolc/adolc.h" 26 typedef adouble IssmDouble; /*for active variables*/ 27 typedef double IssmPDouble; /*for passive variables*/ 27 typedef adouble IssmDouble; /*for active variables*/ 28 typedef acomplex IssmComplex; /*for active variables*/ 29 typedef double IssmPDouble; /*for passive variables*/ 30 typedef std::complex<double> IssmPComplex; /*for passive variables*/ 28 31 29 32 #elif defined(_HAVE_CODIPACK_) && !defined(_WRAPPERS_) 30 33 /*CoDiPack typedefs*/ 31 34 #include <codi.hpp> 32 typedef codi::RealReverse IssmDouble; 33 typedef double IssmPDouble; 35 typedef codi::RealReverse IssmDouble; 36 //typedef codi::ComplexReverse IssmComplex; //not defined so far 37 typedef double IssmPDouble; 38 typedef std::complex<double> IssmPComplex; 34 39 35 40 /*Non-AD typedefs*/ 36 41 #else 37 typedef double IssmDouble; 38 typedef IssmDouble IssmPDouble; 42 typedef double IssmDouble; 43 typedef std::complex<double> IssmComplex; 44 typedef IssmDouble IssmPDouble; 45 typedef IssmComplex IssmPComplex; 39 46 #endif 40 47 -
issm/trunk-jpl/src/m/classes/fourierlove.m
r26233 r26242 19 19 istemporal = 0; 20 20 n_temporal_iterations = 0; 21 time = 0;21 time = 0; 22 22 love_kernels = 0; 23 23 forcing_type = 0; 24 inner_core_boundary = 0;24 inner_core_boundary = 0; 25 25 core_mantle_boundary = 0; 26 complex_computation = 0; 27 26 28 end 27 29 methods (Static) … … 63 65 self.inner_core_boundary=1; 64 66 self.core_mantle_boundary=2; 67 self.complex_computation=0; 65 68 end % }}} 66 69 function disp(self) % {{{ … … 102 105 md = checkfield(md,'fieldname','love.love_kernels','values',[0 1]); 103 106 md = checkfield(md,'fieldname','love.forcing_type','NaN',1,'Inf',1,'numel',1,'>',0, '<=', 12); 107 md = checkfield(md,'fieldname','love.complex_computation','NaN',1,'Inf',1,'numel',1,'values',[0 1]); 104 108 105 109 md = checkfield(md,'fieldname','love.istemporal','values',[0 1]); … … 140 144 WriteData(fid,prefix,'object',self,'fieldname','istemporal','format','Boolean'); 141 145 WriteData(fid,prefix,'object',self,'fieldname','n_temporal_iterations','format','Integer'); 146 WriteData(fid,prefix,'object',self,'fieldname','complex_computation','format','Boolean'); 142 147 %note: no need to marshall the time vector, we have frequencies 143 148 WriteData(fid,prefix,'object',self,'fieldname','love_kernels','format','Boolean'); -
issm/trunk-jpl/src/m/solve/loadresultfromdisk.m
r25300 r26242 49 49 N=fread(fid,1,'int'); 50 50 field=fread(fid,[N M],'int')'; 51 elseif type==5, 52 N=fread(fid,1,'int'); 53 fieldr=fread(fid,[N M],'double')'; 54 fieldi=fread(fid,[N M],'double')'; 55 field=complex(fieldr,fieldi); 51 56 else 52 57 error(['cannot read data of type ' num2str(type) ]); -
issm/trunk-jpl/test/NightlyRun/test2084.m
r26235 r26242 26 26 md.materials.lame_lambda=md.materials.lame_mu*0+5e17; 27 27 md.materials.issolid=[1 0 1 1 1 1]'; 28 md.materials.rheologymodel= 2*ones(md.materials.numlayers,1);28 md.materials.rheologymodel=0*ones(md.materials.numlayers,1); 29 29 md.materials.burgers_mu=md.materials.lame_mu/3; 30 30 md.materials.burgers_viscosity=md.materials.viscosity/10;
Note:
See TracChangeset
for help on using the changeset viewer.