Changeset 26242


Ignore:
Timestamp:
05/05/21 15:40:27 (4 years ago)
Author:
Eric.Larour
Message:

CHG: implemented templated version of the love_core routine, to allow
for IssmComplex and (IssmQuad tuypes in the future). Created new IssmComplex
type.

Location:
issm/trunk-jpl
Files:
13 edited

Legend:

Unmodified
Added
Removed
  • issm/trunk-jpl/src/c/analyses/LoveAnalysis.cpp

    r26234 r26242  
    4242        parameters->AddObject(iomodel->CopyConstantObject("md.love.inner_core_boundary",LoveInnerCoreBoundaryEnum));
    4343        parameters->AddObject(iomodel->CopyConstantObject("md.love.core_mantle_boundary",LoveCoreMantleBoundaryEnum));
     44        parameters->AddObject(iomodel->CopyConstantObject("md.love.complex_computation",LoveComplexComputationEnum));
    4445}/*}}}*/
    4546void LoveAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
  • issm/trunk-jpl/src/c/analyses/SealevelchangeAnalysis.cpp

    r26222 r26242  
    6666
    6767        /*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);
    7070    iomodel->FetchDataToInput(inputs,elements,"md.initialization.sealevel",SealevelEnum);
    7171
  • issm/trunk-jpl/src/c/classes/Elements/Tria.cpp

    r26238 r26242  
    71697169
    71707170        IssmDouble sealevel[3]={0};
     7171        int i,e,l,nbar;
    71717172
    71727173        if(loads->sealevelloads){
    7173                 for(int i=0;i<NUMVERTICES;i++) {
     7174                for(i=0;i<NUMVERTICES;i++) {
    71747175                        if(slgeom->lids[this->vertices[i]->lid]!=this->lid)continue;
    7175                         for (int e=0;e<nel;e++){
     7176                        for (e=0;e<nel;e++){
    71767177                                sealevel[i]+=G[i*nel+e]*(loads->sealevelloads[e]+loads->loads[e]);
    71777178                        }
    7178                         for(int l=0;l<SLGEOM_NUMLOADS;l++){
    7179                                 int nbar=slgeom->nbar[l];
    7180                                 for (int e=0;e<nbar;e++){
     7179                        for(l=0;l<SLGEOM_NUMLOADS;l++){
     7180                                nbar=slgeom->nbar[l];
     7181                                for (e=0;e<nbar;e++){
    71817182                                        sealevel[i]+=Gsub[l][i*nbar+e]*(loads->subloads[l][e]);
    71827183                                }
    71837184                                if(l==SLGEOM_OCEAN){
    7184                                         for (int e=0;e<nbar;e++){
     7185                                        for (e=0;e<nbar;e++){
    71857186                                                sealevel[i]+=Gsub[l][i*nbar+e]*(loads->subsealevelloads[e]);
    71867187                                        }
     
    71907191        }
    71917192        else{  //this is the initial convolution where only loads are provided
    7192                 for(int i=0;i<NUMVERTICES;i++) {
     7193                for(i=0;i<NUMVERTICES;i++) {
    71937194                        if(slgeom->lids[this->vertices[i]->lid]!=this->lid)continue;
    7194                         for (int e=0;e<nel;e++){
     7195                        for (e=0;e<nel;e++){
    71957196                                sealevel[i]+=G[i*nel+e]*(loads->loads[e]);
    71967197                        }
    7197                         for(int l=0;l<SLGEOM_NUMLOADS;l++){
    7198                                 int nbar=slgeom->nbar[l];
    7199                                 for (int e=0;e<nbar;e++){
     7198                        for(l=0;l<SLGEOM_NUMLOADS;l++){
     7199                                nbar=slgeom->nbar[l];
     7200                                for (e=0;e<nbar;e++){
    72007201                                        sealevel[i]+=Gsub[l][i*nbar+e]*(loads->subloads[l][e]);
    72017202                                }
     
    72067207        /*store values computed on vertices, but don't repeat the computation if another element already computed it!:*/
    72077208        if(percpu){
    7208                 for(int i=0;i<NUMVERTICES;i++){
     7209                for(i=0;i<NUMVERTICES;i++){
    72097210                        if(slgeom->lids[this->vertices[i]->lid]==this->lid)sealevelout[this->vertices[i]->lid]=sealevel[i];
    72107211                }
    72117212        }
    72127213        else{
    7213                 for(int i=0;i<NUMVERTICES;i++) sealevelout[i]=sealevel[i];
     7214                for(i=0;i<NUMVERTICES;i++) sealevelout[i]=sealevel[i];
    72147215        }
    72157216
  • issm/trunk-jpl/src/c/classes/ExternalResults/GenericExternalResult.h

    r25531 r26242  
    679679#endif
    680680
     681        /*Specific instantiations for IssmComplex*: */
     682template <> 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/*}}}*/
     701template <> 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
    681750        /*Specifics instantiations for Vector*/
    682751        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  
    99#include "../modules/modules.h"
    1010#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:*/
     14class 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:*/
     41template<typename doubletype> doubletype                 angular_frequency(IssmDouble frequency); //pure declaration
     42template <> IssmDouble                     angular_frequency<IssmDouble>(IssmDouble frequency){ /*{{{*/
     43        return 2.0*PI*frequency;
     44} /*}}}*/
     45template <> 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} /*}}}*/
     49template<typename doubletype> void                       allgesv(int* pnyi, int* pnrhs, doubletype* yilocal, int* plda, int* ipiv, doubletype* rhslocal, int* pldb, int* pinfo);
     50template <> 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} /*}}}*/
     53template <> 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} /*}}}*/
     57template<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}/*}}}*/
     62template<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}/*}}}*/
     103template<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}/*}}}*/
     125template<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}/*}}}*/
     155template <typename doubletype> void        GetEarthRheology(doubletype* pla, doubletype* pmu, int layer_index, doubletype omega,  Matlitho* matlitho){ /*{{{*/
    45156
    46157        //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];
    51164
    52165        if (vi!=0 && omega!=0.0){ //take into account viscosity in the rigidity if the material isn't a perfect fluid
    53                                    //Otherwise return the elastic value
    54                 IssmDouble ka=la + 2.0/3.0*mu; //Bulk modulus
     166                //Otherwise return the elastic value
     167                IssmDouble ka=la0 + 2.0/3.0*mu0; //Bulk modulus
    55168                if (rheo==2){//EBM
    56169                        IssmDouble alpha=matlitho->ebm_alpha[layer_index];
     
    58171                        IssmDouble taul=matlitho->ebm_taul[layer_index];
    59172                        IssmDouble tauh=matlitho->ebm_tauh[layer_index];
    60                         IssmDouble hf1,hf2,U1,U2;
     173                        IssmDouble hf1,hf2;
     174                        doubletype U1,U2;
    61175                        IssmDouble* a=xNew<IssmDouble>(2);
    62176                        IssmDouble* b=xNew<IssmDouble>(1);
     
    79193
    80194                        mu=mu/(1.0+ alpha*delta/(pow(tauh,alpha)-pow(taul,alpha))*(U1 + omega*U2) -mu/vi/omega);
    81                         la=ka-2.0/3.0*mu;
     195                        la=ka-2.0/3.0*mu;
    82196
    83197                        xDelete<IssmDouble>(a);
     
    88202                        IssmDouble mu2=matlitho->burgers_mu[layer_index];
    89203
    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                }
    93207                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          *pla=la;
    100          *pmu=mu;
     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;
    101215
    102216} /*}}}*/
    103 IssmDouble GetGravity(IssmDouble r2, int layer_index, FemModel* femmodel, Matlitho* matlitho){ /*{{{*/
     217IssmDouble                                 GetGravity(IssmDouble r2, int layer_index, FemModel* femmodel, Matlitho* matlitho,LoveVariables* vars){ /*{{{*/
    104218        //computes gravity at radius r2
    105219        IssmDouble* EarthMass;
    106220        IssmDouble g, GG;
    107221
    108         femmodel->parameters->FindParam(&EarthMass,&matlitho->numlayers,LoveEarthMassEnum);
     222        EarthMass=vars->EarthMass;
    109223        femmodel->parameters->FindParam(&GG,LoveGravitationalConstantEnum);
    110224        IssmDouble ro=matlitho->density[layer_index];
     
    120234        return  g= GG*M/pow(r2,2.0);
    121235}/*}}}*/
    122 void fill_yi_prefactor(IssmDouble* yi_prefactor, int* pdeg, IssmDouble* pomega, FemModel* femmodel, Matlitho* matlitho){ /*{{{*/
     236template <typename doubletype> void        fill_yi_prefactor(doubletype* yi_prefactor, int* pdeg, doubletype* pomega, FemModel* femmodel, Matlitho* matlitho, LoveVariables* vars){ /*{{{*/
    123237        //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;
    137253
    138254        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];
    141257                int deg=*pdeg;
    142                 IssmDouble omega=*pomega;       
     258                doubletype omega=*pomega;       
    143259                fn=deg*(deg+1.0);
    144260
    145261                for (int layer_index=starting_layer;layer_index<matlitho->numlayers;layer_index++){
    146262
    147                                 ro=matlitho->density[layer_index];
    148                                 issolid=matlitho->issolid[layer_index];
    149                                 if(issolid==1){
    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
    152268                                /*_______Expressions*/
    153269                                flm=(la+2.0*mu);
     
    172288                                xmax=(matlitho->radius[layer_index+1])/ra;
    173289                                dr = (xmax -xmin)/nstep;
    174                                 x=xmin;
     290                                x=xmin;
    175291                                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);
    177293
    178294                                        nindex=layer_index*nstep*36+n*36;
     
    191307                        }
    192308                }
    193 
    194                 xDelete<IssmDouble>(f);
    195         /*}}}*/
     309                /*}}}*/
    196310        } else if (pdeg) { // degree dependent terms /*{{{*/
    197                 int deg=*pdeg;
    198                 fn=(deg*(deg+1.0));
     311                int deg=*pdeg;
     312                fn=(deg*(deg+1.0));
    199313
    200314                for (int layer_index=starting_layer;layer_index<matlitho->numlayers;layer_index++){
    201315                        ro=matlitho->density[layer_index];
    202316                        issolid=matlitho->issolid[layer_index];
    203        
     317
    204318                        /*_______Expressions*/
    205319                        fgr=4.0*PI*GG*ro*ra;
    206          
     320
    207321                        xmin=matlitho->radius[layer_index]/ra;
    208322                        xmax=(matlitho->radius[layer_index+1])/ra;
    209323                        dr = (xmax -xmin)/nstep;
    210                         x=xmin;
     324                        x=xmin;
    211325                        for (int n=0;n<nstep;n++){
    212                                  nindex=layer_index*nstep*36+n*36;
    213                                  g=GetGravity(x*ra,layer_index,femmodel,matlitho);
    214        
    215                                  if(issolid==1){
    216                                  yi_prefactor[nindex+ 1*6+3]= fn/x;                  // in dy[1*6+3]
    217                                  yi_prefactor[nindex+ 5*6+2]= -(fgr/g0*fn)/x;        // in dy[5*6+2]
    218                                  yi_prefactor[nindex+ 5*6+4]= fn/(x*x);              // in dy[5*6+4]
    219                                  } else {
    220                                  yi_prefactor[nindex+ 1*6+0]= (-4.0*(fgr/g)+fn/x)/x; // in dy[1*6+0] liquid layer
    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                                }
    222336                                x=x+dr;
    223337                        }
    224338                }
    225         /*}}}*/
     339                /*}}}*/
    226340        } else { // static terms /*{{{*/
    227341                for (int layer_index=starting_layer;layer_index<matlitho->numlayers;layer_index++){
    228342                        ro=matlitho->density[layer_index];
    229343                        issolid=matlitho->issolid[layer_index];
    230        
     344
    231345                        /*_______Expressions*/
    232346                        frhg0=ro*g0*ra/mu0;
     
    236350                        xmax=(matlitho->radius[layer_index+1])/ra;
    237351                        dr = (xmax -xmin)/nstep;
    238                         x=xmin;
    239                         for (int n=0;n<nstep;n++){
    240                                  g=GetGravity(x*ra,layer_index,femmodel,matlitho);
    241                                  nindex=layer_index*nstep*36+n*36;
    242                                  if(issolid==1){
    243                                          yi_prefactor[nindex+ 1*6+5]= -frhg0;       // in dy[1*6+5]
    244                                          yi_prefactor[nindex+ 2*6+0]= -1.0/x;       // in dy[2*6+0]
    245                                          yi_prefactor[nindex+ 2*6+2]= 1.0/x;        // in dy[2*6+2]
    246                                          yi_prefactor[nindex+ 3*6+3]= -3.0/x;       // in dy[3*6+3]
    247                                          yi_prefactor[nindex+ 3*6+4]= -frhg0/x;     // in dy[3*6+4]
    248                                          yi_prefactor[nindex+ 4*6+0]= fgr/g0;       // in dy[4*6+0]
    249                                          yi_prefactor[nindex+ 4*6+5]= 1.0;          // in dy[4*6+5]
    250                                          yi_prefactor[nindex+ 5*6+5]= -2.0/x;       // in dy[5*6+5]
    251                                  } else {
    252                                          yi_prefactor[nindex+ 0*6+0]= fgr/g;        // in dy[0*6+0] liquid layer
    253                                          yi_prefactor[nindex+ 0*6+1]= 1.0;          // in dy[0*6+1] liquid layer
    254                                          yi_prefactor[nindex+ 1*6+1]= -2.0/x-fgr/g; // in dy[1*6+1] liquid layer
    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                                }
    256370                                x=x+dr;
    257371                        }
    258372                }
    259         /*}}}*/
    260         }
    261 }/*}}}*/
    262 IssmDouble* yi_derivatives(IssmDouble* y, int layer_index, int n, IssmDouble* yi_prefactor, FemModel* femmodel, Matlitho* matlitho){ /*{{{*/
     373                /*}}}*/
     374        }
     375}/*}}}*/
     376template <typename doubletype> void        yi_derivatives(doubletype* dydx, doubletype* y, int layer_index, int n, doubletype* yi_prefactor, FemModel* femmodel, Matlitho* matlitho){ /*{{{*/
    263377        //computes yi derivatives at r=radius[layer_index]+ n/nstep*(radius[layer_index+1]-radius[layer_index])
    264378
    265379        IssmDouble issolid=matlitho->issolid[layer_index];
    266380        int iy,id,ny, nindex, nstep;
    267         IssmDouble* dydx=xNewZeroInit<IssmDouble>(6);
    268         IssmDouble* dy=xNewZeroInit<IssmDouble>(36);
    269381        femmodel->parameters->FindParam(&nstep,LoveIntStepsPerLayerEnum);
    270382
    271383        /*{{{*/ /* 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          if(issolid==1){
    337                  ny = 6;
    338          } else {
    339                  ny = 2;
    340          }
    341          
    342          for (id=0;id<ny;id++){
     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++){
    343455                for (iy=0;iy<ny;iy++){
    344456                        nindex=layer_index*nstep*36+n*36;
    345457                        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}/*}}}*/
     462template <typename doubletype> void        propagate_yi_euler(IssmDouble* y, IssmDouble xmin, IssmDouble xmax, int layer_index, IssmDouble* yi_prefactor, FemModel* femmodel, Matlitho* matlitho){ /*{{{*/
    352463        //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?
    353464        //euler method
     
    355466        femmodel->parameters->FindParam(&nstep,LoveIntStepsPerLayerEnum);
    356467
    357         IssmDouble* dydx=xNewZeroInit<IssmDouble>(6);
     468        IssmDouble* dydx=xNewZeroInit<IssmDouble>(6);
    358469        IssmDouble dr = (xmax -xmin)/nstep;
    359         IssmDouble x=xmin;
    360     for(int i = 0;i<nstep;i++){
    361         dydx=yi_derivatives(y,layer_index, i,yi_prefactor,femmodel,matlitho);
    362         for (int j=0;j<6;j++){
    363                 y[j]+=dydx[j]*dr;
    364         }
    365         x = x + dr;
    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        }
    367478        xDelete<IssmDouble>(dydx);
    368479}/*}}}*/
    369 void propagate_yi_RK2(IssmDouble* y, IssmDouble xmin, IssmDouble xmax, int layer_index, IssmDouble* yi_prefactor, FemModel* femmodel, Matlitho* matlitho){ /*{{{*/
     480template <typename doubletype> void        propagate_yi_RK2(doubletype* y, IssmDouble xmin, IssmDouble xmax, int layer_index, doubletype* yi_prefactor, FemModel* femmodel, Matlitho* matlitho){ /*{{{*/
    370481        //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?
    371482        //Implements Runge-Kutta 2nd order (midpoint method)
     
    373484        femmodel->parameters->FindParam(&nstep,LoveIntStepsPerLayerEnum);
    374485
    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};
    382493
    383494        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}/*}}}*/
     508template <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);
    387542        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
    395555        xDelete<IssmDouble>(k1);
    396556        xDelete<IssmDouble>(k2);
     
    401561        xDelete<IssmDouble>(y3);
    402562}/*}}}*/
    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){ /*{{{*/
     563template <typename doubletype> void        Innersphere_boundaryconditions(doubletype* yi, int layer_index, int deg, doubletype omega, FemModel* femmodel, Matlitho* matlitho, LoveVariables* vars){ /*{{{*/
    459564        //fills the boundary conditions at the bottom of layer[layer_index] in yi[0:2][0:5]
    460565
     
    463568        IssmDouble  g0,r0,mu0, GG;
    464569        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);
    469572        femmodel->parameters->FindParam(&GG,LoveGravitationalConstantEnum);
     573
     574        g0=vars->g0;
     575        r0=vars->r0;
     576        nyi=vars->nyi;
     577
    470578        IssmDouble ro=matlitho->density[layer_index];
    471579        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;
    474582
    475583        if (layer_index==0){
    476584                // 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);   
    478586        } else {
    479                 GetEarthRheology(&la, &mu,layer_index-1,omega,femmodel,matlitho);   
     587                GetEarthRheology<doubletype>(&la, &mu,layer_index-1,omega,matlitho);   
    480588        }   
    481589
     
    506614        yi[5+nyi*1]=-cst/(r*g0);
    507615        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}/*}}}*/
     618template <typename doubletype> void        build_yi_system(doubletype* yi, int deg, doubletype omega, doubletype* yi_prefactor, FemModel* femmodel, Matlitho* matlitho,LoveVariables* vars) { /*{{{*/
    510619
    511620        IssmDouble  g0,r0,mu0,x,ro1, GG;
    512621        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
    515628        femmodel->parameters->FindParam(&mu0,LoveMu0Enum);
    516         femmodel->parameters->FindParam(&nyi,LoveNYiEquationsEnum);
    517629        femmodel->parameters->FindParam(&GG,LoveGravitationalConstantEnum);
    518         femmodel->parameters->FindParam(&starting_layer,LoveStartingLayerEnum);
    519630        femmodel->parameters->FindParam(&nstep,LoveIntStepsPerLayerEnum);
    520631
    521           IssmDouble xmin,xmax,one,ro,g;
    522           IssmDouble ra=matlitho->radius[matlitho->numlayers];
     632        IssmDouble xmin,xmax,one,ro,g;
     633        IssmDouble ra=matlitho->radius[matlitho->numlayers];
    523634
    524635        for (int i=0;i<6*(matlitho->numlayers+1);i++){
     
    529640
    530641        int ny,is,ii,jj;
    531         IssmDouble ystart[6];
     642        doubletype ystart[6];
    532643        for (int k=0;k<6;k++) ystart[k]=0.0;           
    533  
     644
    534645        int ici = 0;   // Index of current interface
    535646        for (int i = starting_layer; i<matlitho->numlayers;i++){
     
    538649                xmax=(matlitho->radius[i+1])/ra;
    539650
    540                  
     651
    541652                if (matlitho->issolid[i]){
    542                                 ny = 6;
    543                                 is = 0;
    544                                 one= 1.0;
     653                        ny = 6;
     654                        is = 0;
     655                        one= 1.0;
    545656                } else {       
    546                                 ny = 2;
    547                                 is = 4;
    548                                 one= -1.0;
    549                 }
    550        
     657                        ny = 2;
     658                        is = 4;
     659                        one= -1.0;
     660                }
     661
    551662
    552663                for (int j = 0;j<ny;j++){
    553664                        for (int k=0;k<6;k++){ystart[k]=0.0;}
    554665                        ystart[j]= 1.0;
    555                                        
     666
    556667                        // Numerical Integration
    557668                        //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);
    559670                        //propagate_yi_RK4(&ystart[0], xmin, xmax, i, yi_prefactor,femmodel, matlitho);
    560671                        // Boundary Condition matrix - propagation part
     
    562673                        jj = 6*(ici+1)+j+is-3;
    563674                        for (int kk=0;kk<ny;kk++){
    564                                 yi[(ii+kk)+nyi*jj] = ystart[kk]*one;
    565                         }
    566                 }
    567                  
    568                  
     675                                yi[(ii+kk)+nyi*jj] = ystart[kk]*one;
     676                        }
     677                }
     678
     679
    569680                // Boundary Condition matrix - solid regions
    570681                if (matlitho->issolid[i]){
     
    576687                } else { // Boundary Condition matrix - liquid regions
    577688                        ro1=matlitho->density[i];
    578                         g=GetGravity(matlitho->radius[i], i, femmodel,matlitho);
     689                        g=GetGravity(matlitho->radius[i], i, femmodel,matlitho,vars);
    579690                        ii = 6*ici;
    580691                        yi[ii+nyi*(ii+3)] = -1.0;
     
    585696                        yi[(ii+4)+nyi*(ii+4+3)]=-1.0;
    586697                        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);
    588699                        ii = 6*(ici+1);
    589700                        yi[ii+nyi*(ii-1)]=-1.0;
    590701                        yi[ii+nyi*(ii+1)]=yi[(ii+4)+nyi*(ii+1)]*g0/g; // yi(17,14) solution integration 1 of z5 CMB
    591702                        yi[ii+nyi*(ii+2)]=yi[(ii+4)+nyi*(ii+2)]*g0/g; // yi(17,15) solution integration 2 of z5 CMB
    592                           // yi(13,..) y1 CMB
     703                        // yi(13,..) y1 CMB
    593704                        yi[(ii+1)+nyi*(ii-1)]=-ro1*g*ra/mu0;
    594705                        yi[(ii+2)+nyi*(ii)]=-1.0;
     
    599710
    600711
    601         //-- Internal sphere: integration starts here rather than r=0 for numerical reasons
    602         Innersphere_boundaryconditions(yi, starting_layer, deg, omega, femmodel, matlitho);
    603 
    604         //-- Surface conditions
     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
    605716        yi[(nyi-6)+nyi*(nyi-3)]=-1.0;
    606717        yi[(nyi-4)+nyi*(nyi-2)]=-1.0;
     
    608719        yi[(nyi-1)+nyi*(nyi-1)]=deg+1.0;
    609720
    610         //-- Degree 1 special case
     721        //-- Degree 1 special case
    611722        if(deg==1){
    612723                for (int i=0;i<nyi;i++){
     
    615726                yi[(nyi-1)+nyi*(nyi-1)]=1.0;
    616727        }
    617 }/*}}}*/
    618 void yi_boundary_conditions(IssmDouble* yi_righthandside, int deg, FemModel* femmodel, Matlitho* matlitho){ /*{{{*/
     728
     729}/*}}}*/
     730template <typename doubletype> void        yi_boundary_conditions(doubletype* yi_righthandside, int deg, FemModel* femmodel, Matlitho* matlitho,LoveVariables* vars){ /*{{{*/
    619731
    620732        IssmDouble  g0,r0,mu0,ra,rb,rc;
    621         int nyi, forcing_type,icb,cmb;
     733        int nyi, forcing_type,icb,cmb,starting_layer;
    622734        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
    625742        femmodel->parameters->FindParam(&mu0,LoveMu0Enum);
    626         femmodel->parameters->FindParam(&nyi,LoveNYiEquationsEnum);
    627743        femmodel->parameters->FindParam(&forcing_type,LoveForcingTypeEnum);
    628744        femmodel->parameters->FindParam(&icb,LoveInnerCoreBoundaryEnum);
    629745        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
    633748        ra=matlitho->radius[matlitho->numlayers];       
    634749        rb=0;
     
    642757
    643758        IssmDouble ro_mean=EarthMass[matlitho->numlayers-1]/(4.0/3.0*PI*pow(ra,3.0));
    644         xDelete<IssmDouble>(EarthMass);
    645759
    646760        for (int i=0;i<(matlitho->numlayers+1)*6;i++) yi_righthandside[i]=0.0;
     
    648762        switch (forcing_type) {
    649763
    650         //-- forcings at the Inner Core Boundary
    651         case 1: //'ICB --Volumetric Potential'
    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 Boundary
    667         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 surface
    683         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}/*}}}*/
     814template <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){ /*{{{*/
    701815
    702816        IssmDouble  g0,r0,mu0,loveratio,underflow_tol;
     
    704818        int nyi,starting_layer, dummy;
    705819        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
    708828        femmodel->parameters->FindParam(&mu0,LoveMu0Enum);
    709         femmodel->parameters->FindParam(&nyi,LoveNYiEquationsEnum);
    710         femmodel->parameters->FindParam(&starting_layer,LoveStartingLayerEnum);
    711829        femmodel->parameters->FindParam(&allow_layer_deletion,LoveAllowLayerDeletionEnum);
    712830        femmodel->parameters->FindParam(&underflow_tol,LoveUnderflowTolEnum);
    713831        femmodel->parameters->FindParam(&frequencies,&dummy,LoveFrequenciesEnum);
    714         IssmDouble ra=matlitho->radius[matlitho->numlayers];
     832        IssmDouble ra=matlitho->radius[matlitho->numlayers];
    715833        bool exit=false;
    716834        int lda,ldb;
     
    719837                lda=nyi;
    720838                ldb=nyi;
    721                 IssmDouble*  yilocal=xNew<IssmDouble>(nyi*nyi); // we will need to redeclare these inside here as nyi changes
    722                 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);
    723841
    724842                //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
     
    734852                int nrhs=1; // number of right hand size columns
    735853
    736                 dgesv_(&nyi, &nrhs, yilocal, &lda, ipiv, rhslocal, &ldb, &info);
     854                allgesv<doubletype>(&nyi, &nrhs, yilocal, &lda, ipiv, rhslocal, &ldb, &info);
     855               
    737856                xDelete<int>(ipiv);
    738 
    739                 if(VerboseSolution() && info!=0){
     857               
     858                if(VerboseModule() && info!=0){
    740859                        _printf0_("love core warning in DGESV : LAPACK linear equation solver couldn't resolve the system");
    741860                        printf("%s %s %s %s\n", "i","j","yi[i+nyi*j]","rhs[i]");
     
    751870                *lovek = rhslocal[nyi-1]*ra*g0;
    752871
    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);
    760879
    761880                loveratio = abs(loveh1/loveh1s); //ratio of center to surface love numbers, determines if we should remove layers
     
    763882                if (abs(lovek1/lovek1s) < loveratio) loveratio = abs(lovek1/lovek1s);
    764883
    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])){
    766885                        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.*/
    767889                }
    768890
     
    775897                        nyi-=6;
    776898                        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;
    780901
    781902                        for (int i=0;i<nyi;i++){//shift everything down by 1 layer
     
    786907                        }
    787908
    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 different
     909                        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
    789910                } else { //we are ready to save the outputs and break the main loop
    790911
    791                 save_results:
     912save_results:
    792913                        for (int i=0;i<nyi;i++){
    793914                                rhs[i]=rhslocal[i];
     
    811932
    812933                        exit = true;
    813                 }
    814                 xDelete<IssmDouble>(yilocal);
    815                 xDelete<IssmDouble>(rhslocal);
    816         }
     934                }
     935                xDelete<doubletype>(yilocal);
     936                xDelete<doubletype>(rhslocal);
     937        }
    817938        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}/*}}}*/
     941template <typename doubletype> void        love_freq_to_temporal(doubletype* LoveHt,doubletype* LoveLt,doubletype* LoveKt,doubletype* LoveHf,doubletype* LoveLf,doubletype* LoveKf, FemModel* femmodel){ /*{{{*/
    918942        //Transforms all frequency-dependent love numbers into time-dependent love numbers
    919943        int nfreq,sh_nmax,sh_nmin,indxi,indf, NTit;
    920         IssmDouble meanh,meanl,meank,dh,dl,dk;
    921944
    922945        femmodel->parameters->FindParam(&nfreq,LoveNfreqEnum);
     
    924947        femmodel->parameters->FindParam(&sh_nmin,LoveShNminEnum);
    925948        femmodel->parameters->FindParam(&NTit,LoveNTemporalIterationsEnum);
    926        
     949
    927950        int nt=nfreq/2/NTit;
    928         IssmDouble* xi=postwidder_coef(NTit);
     951        doubletype* xi=postwidder_coef<doubletype>(NTit);
    929952
    930953        for (int d=sh_nmin;d<sh_nmax+1;d++){
    931954                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:*/
     964LoveVariables*                             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} /*}}}*/
     1000template <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");
    9401025
    9411026        /*recover materials parameters: there is only one Matlitho, chase it down the hard way:*/
    942         Matlitho* matlitho=NULL;
    9431027        for (Object* & object: femmodel->materials->objects){
    9441028                Material* material=xDynamicCast<Material*>(object);
     
    9501034        _assert_(matlitho);
    9511035
    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: */
    9671037        femmodel->parameters->FindParam(&save_results,SaveResultsEnum);
    968 
    969         /*recover love number parameters: */
    970 
    9711038        femmodel->parameters->FindParam(&nfreq,LoveNfreqEnum);
    9721039        femmodel->parameters->FindParam(&frequencies,&dummy,LoveFrequenciesEnum); _assert_(nfreq==dummy);
     
    9811048        femmodel->parameters->FindParam(&istemporal,LoveIsTemporalEnum);
    9821049        femmodel->parameters->FindParam(&nstep,LoveIntStepsPerLayerEnum);
     1050        femmodel->parameters->FindParam(&complex_computation,LoveComplexComputationEnum);
     1051
    9831052
    9841053        /*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));
    9881057
    9891058        /*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);
    9991066
    10001067        //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);
    10021069        for(int deg=sh_nmin;deg<sh_nmax+1;deg++){
    10031070
    10041071                //precalculate yi coefficients that depend on degree but not frequency
    1005                 fill_yi_prefactor(yi_prefactor, &deg, NULL,femmodel, matlitho);
     1072                fill_yi_prefactor<doubletype>(yi_prefactor, &deg, NULL,femmodel, matlitho,vars);
    10061073
    10071074                for (int fr=0;fr<nfreq;fr++){
    1008                         omega=2.0*PI*frequencies[fr]; //angular frequency
     1075                        omega=angular_frequency<doubletype>(frequencies[fr]);
    10091076
    10101077                        //precalculate yi coefficients that depend on degree and frequency
    1011                         fill_yi_prefactor(yi_prefactor, &deg,&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, &deg,&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);
    10181085
    10191086                        LoveHf[deg*nfreq+fr]=loveh;
     
    10211088                        LoveLf[deg*nfreq+fr]=lovel;
    10221089
    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);
    10371101
    10381102
    10391103        //Temporal love numbers
    1040         if (istemporal){
     1104        if (istemporal && !complex_computation){
    10411105                int NTit;
    10421106                femmodel->parameters->FindParam(&NTit,LoveNTemporalIterationsEnum);
    10431107                int nt = nfreq/2/NTit;
    10441108
    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));
    10631127
    10641128
     
    10821146        /*Only when love_kernels is on*/
    10831147        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));
    10851149                //femmodel->results->AddObject(new GenericExternalResult<IssmDouble*>(femmodel->results->Size()+1,LoveKernelsImagEnum,LoveKernelsImag,(sh_nmax+1)*(matlitho->numlayers+1)*6,nfreq,0,0));
    10861150        }
     
    10881152        /*Free resources:*/
    10891153        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);
    10951157        //xDelete<IssmDouble>(LoveLi);
    1096         xDelete<IssmDouble>(LoveKernelsReal);
    1097         xDelete<IssmDouble>(LoveKernelsImag);
     1158        xDelete<doubletype>(LoveKernels);
    10981159} /*}}}*/
     1160
     1161/*cores and template instantiations:*/
     1162/*template instantiations :{{{*/
     1163template void love_core_template<IssmDouble>(FemModel* femmodel);
     1164template void love_core_template<IssmComplex>(FemModel* femmodel);
     1165template void        fill_yi_prefactor<IssmDouble>(IssmDouble* yi_prefactor, int* pdeg, IssmDouble* pomega, FemModel* femmodel, Matlitho* matlitho, LoveVariables* vars);
     1166template void        fill_yi_prefactor<IssmComplex>(IssmComplex* yi_prefactor, int* pdeg, IssmComplex* pomega, FemModel* femmodel, Matlitho* matlitho, LoveVariables* vars);
     1167template void        GetEarthRheology<IssmDouble>(IssmDouble* pla, IssmDouble* pmu, int layer_index, IssmDouble omega,  Matlitho* matlitho);
     1168template void        GetEarthRheology<IssmComplex>(IssmComplex* pla, IssmComplex* pmu, int layer_index, IssmComplex omega,  Matlitho* matlitho);
     1169template void        yi_boundary_conditions<IssmDouble>(IssmDouble* yi_righthandside, int deg, FemModel* femmodel, Matlitho* matlitho,LoveVariables* vars);
     1170template void        yi_boundary_conditions<IssmComplex>(IssmComplex* yi_righthandside, int deg, FemModel* femmodel, Matlitho* matlitho,LoveVariables* vars);
     1171template void        yi_derivatives<IssmDouble>(IssmDouble* dydx, IssmDouble* y, int layer_index, int n, IssmDouble* yi_prefactor, FemModel* femmodel, Matlitho* matlitho);
     1172template void        yi_derivatives<IssmComplex>(IssmComplex* dydx, IssmComplex* y, int layer_index, int n, IssmComplex* yi_prefactor, FemModel* femmodel, Matlitho* matlitho);
     1173template void        propagate_yi_RK2<IssmDouble>(IssmDouble* y, IssmDouble xmin, IssmDouble xmax, int layer_index, IssmDouble* yi_prefactor, FemModel* femmodel, Matlitho* matlitho);
     1174template void        propagate_yi_RK2<IssmComplex>(IssmComplex* y, IssmDouble xmin, IssmDouble xmax, int layer_index, IssmComplex* yi_prefactor, FemModel* femmodel, Matlitho* matlitho);
     1175template void        Innersphere_boundaryconditions<IssmDouble>(IssmDouble* yi, int layer_index, int deg, IssmDouble omega, FemModel* femmodel, Matlitho* matlitho, LoveVariables* vars);
     1176template void        Innersphere_boundaryconditions<IssmComplex>(IssmComplex* yi, int layer_index, int deg, IssmComplex omega, FemModel* femmodel, Matlitho* matlitho, LoveVariables* vars);
     1177template void        build_yi_system<IssmDouble>(IssmDouble* yi, int deg, IssmDouble omega, IssmDouble* yi_prefactor, FemModel* femmodel, Matlitho* matlitho,LoveVariables* vars);
     1178template void        build_yi_system<IssmComplex>(IssmComplex* yi, int deg, IssmComplex omega, IssmComplex* yi_prefactor, FemModel* femmodel, Matlitho* matlitho,LoveVariables* vars);
     1179template 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);
     1180template 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);
     1181template IssmDouble  factorial<IssmDouble>(int n);
     1182template IssmDouble* postwidder_coef<IssmDouble>(int NTit);
     1183template IssmDouble  n_C_r<IssmDouble>(int n, int r);
     1184template void         postwidder_transform<IssmDouble>(IssmDouble* Lovet, IssmDouble* Lovef,int d, int t, int NTit, IssmDouble* xi, FemModel* femmodel);
     1185
     1186/*}}}*/
     1187void           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  
    256256syn keyword cConstant LockFileNameEnum
    257257syn keyword cConstant LoveAllowLayerDeletionEnum
     258syn keyword cConstant LoveCoreMantleBoundaryEnum
     259syn keyword cConstant LoveEarthMassEnum
    258260syn keyword cConstant LoveForcingTypeEnum
    259261syn keyword cConstant LoveFrequenciesEnum
     262syn keyword cConstant LoveIsTemporalEnum
    260263syn keyword cConstant LoveG0Enum
     264syn keyword cConstant LoveGravitationalConstantEnum
     265syn keyword cConstant LoveInnerCoreBoundaryEnum
     266syn keyword cConstant LoveComplexComputationEnum
     267syn keyword cConstant LoveIntStepsPerLayerEnum
    261268syn keyword cConstant LoveKernelsEnum
    262269syn keyword cConstant LoveMu0Enum
    263270syn keyword cConstant LoveNfreqEnum
     271syn keyword cConstant LoveNTemporalIterationsEnum
     272syn keyword cConstant LoveNYiEquationsEnum
    264273syn keyword cConstant LoveR0Enum
    265274syn keyword cConstant LoveShNmaxEnum
    266275syn keyword cConstant LoveShNminEnum
     276syn keyword cConstant LoveStartingLayerEnum
     277syn keyword cConstant LoveUnderflowTolEnum
    267278syn keyword cConstant MassFluxSegmentsEnum
    268279syn keyword cConstant MassFluxSegmentsPresentEnum
     
    783794syn keyword cConstant SealevelGrotm2Enum
    784795syn keyword cConstant SealevelGrotm3Enum
     796syn keyword cConstant SealevelGUrotm1Enum
     797syn keyword cConstant SealevelGUrotm2Enum
     798syn keyword cConstant SealevelGUrotm3Enum
     799syn keyword cConstant SealevelGNrotm1Enum
     800syn keyword cConstant SealevelGNrotm2Enum
     801syn keyword cConstant SealevelGNrotm3Enum
     802syn keyword cConstant SealevelGErotm1Enum
     803syn keyword cConstant SealevelGErotm2Enum
     804syn keyword cConstant SealevelGErotm3Enum
    785805syn keyword cConstant SealevelRSLBarystaticEnum
    786806syn keyword cConstant SealevelRSLRateEnum
     
    15281548syn keyword cType GenericParam
    15291549syn keyword cType GiaDeflectionCoreArgs
     1550syn keyword cType GrdLoads
    15301551syn keyword cType Hook
    15311552syn keyword cType Input
  • issm/trunk-jpl/src/c/shared/Enum/EnumDefinitions.h

    r26233 r26242  
    258258        LoveGravitationalConstantEnum,
    259259        LoveInnerCoreBoundaryEnum,
     260        LoveComplexComputationEnum,
    260261        LoveIntStepsPerLayerEnum,
    261262        LoveKernelsEnum,
  • issm/trunk-jpl/src/c/shared/Enum/EnumToStringx.cpp

    r26222 r26242  
    258258                case LockFileNameEnum : return "LockFileName";
    259259                case LoveAllowLayerDeletionEnum : return "LoveAllowLayerDeletion";
     260                case LoveCoreMantleBoundaryEnum : return "LoveCoreMantleBoundary";
     261                case LoveEarthMassEnum : return "LoveEarthMass";
    260262                case LoveForcingTypeEnum : return "LoveForcingType";
    261263                case LoveFrequenciesEnum : return "LoveFrequencies";
     264                case LoveIsTemporalEnum : return "LoveIsTemporal";
    262265                case LoveG0Enum : return "LoveG0";
     266                case LoveGravitationalConstantEnum : return "LoveGravitationalConstant";
     267                case LoveInnerCoreBoundaryEnum : return "LoveInnerCoreBoundary";
     268                case LoveComplexComputationEnum : return "LoveComplexComputation";
     269                case LoveIntStepsPerLayerEnum : return "LoveIntStepsPerLayer";
    263270                case LoveKernelsEnum : return "LoveKernels";
    264271                case LoveMu0Enum : return "LoveMu0";
    265272                case LoveNfreqEnum : return "LoveNfreq";
     273                case LoveNTemporalIterationsEnum : return "LoveNTemporalIterations";
     274                case LoveNYiEquationsEnum : return "LoveNYiEquations";
    266275                case LoveR0Enum : return "LoveR0";
    267276                case LoveShNmaxEnum : return "LoveShNmax";
    268277                case LoveShNminEnum : return "LoveShNmin";
     278                case LoveStartingLayerEnum : return "LoveStartingLayer";
     279                case LoveUnderflowTolEnum : return "LoveUnderflowTol";
    269280                case MassFluxSegmentsEnum : return "MassFluxSegments";
    270281                case MassFluxSegmentsPresentEnum : return "MassFluxSegmentsPresent";
     
    785796                case SealevelGrotm2Enum : return "SealevelGrotm2";
    786797                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";
    787807                case SealevelRSLBarystaticEnum : return "SealevelRSLBarystatic";
    788808                case SealevelRSLRateEnum : return "SealevelRSLRate";
  • issm/trunk-jpl/src/c/shared/Enum/StringToEnumx.cpp

    r26222 r26242  
    264264   if(stage==3){
    265265              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;
    266268              else if (strcmp(name,"LoveForcingType")==0) return LoveForcingTypeEnum;
    267269              else if (strcmp(name,"LoveFrequencies")==0) return LoveFrequenciesEnum;
     270              else if (strcmp(name,"LoveIsTemporal")==0) return LoveIsTemporalEnum;
    268271              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;
    269276              else if (strcmp(name,"LoveKernels")==0) return LoveKernelsEnum;
    270277              else if (strcmp(name,"LoveMu0")==0) return LoveMu0Enum;
    271278              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;
    272281              else if (strcmp(name,"LoveR0")==0) return LoveR0Enum;
    273282              else if (strcmp(name,"LoveShNmax")==0) return LoveShNmaxEnum;
    274283              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;
    275286              else if (strcmp(name,"MassFluxSegments")==0) return MassFluxSegmentsEnum;
    276287              else if (strcmp(name,"MassFluxSegmentsPresent")==0) return MassFluxSegmentsPresentEnum;
     
    372383              else if (strcmp(name,"SealevelchangeGRigid")==0) return SealevelchangeGRigidEnum;
    373384              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;
    375389              else if (strcmp(name,"SolidearthSettingsGRD")==0) return SolidearthSettingsGRDEnum;
    376390              else if (strcmp(name,"SolidearthSettingsRunFrequency")==0) return SolidearthSettingsRunFrequencyEnum;
     
    383397              else if (strcmp(name,"SealevelchangeRequestedOutputs")==0) return SealevelchangeRequestedOutputsEnum;
    384398              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;
    389400              else if (strcmp(name,"SealevelchangeRunCount")==0) return SealevelchangeRunCountEnum;
    390401              else if (strcmp(name,"SealevelchangeTransitions")==0) return SealevelchangeTransitionsEnum;
     
    495506              else if (strcmp(name,"TimesteppingType")==0) return TimesteppingTypeEnum;
    496507              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;
    498512              else if (strcmp(name,"ToolkitsOptionsAnalyses")==0) return ToolkitsOptionsAnalysesEnum;
    499513              else if (strcmp(name,"ToolkitsOptionsStrings")==0) return ToolkitsOptionsStringsEnum;
     
    506520              else if (strcmp(name,"TransientIshydrology")==0) return TransientIshydrologyEnum;
    507521              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;
    512523              else if (strcmp(name,"TransientIsmovingfront")==0) return TransientIsmovingfrontEnum;
    513524              else if (strcmp(name,"TransientIsoceancoupling")==0) return TransientIsoceancouplingEnum;
     
    618629              else if (strcmp(name,"DistanceToCalvingfront")==0) return DistanceToCalvingfrontEnum;
    619630              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;
    621635              else if (strcmp(name,"Domain2Dvertical")==0) return Domain2DverticalEnum;
    622636              else if (strcmp(name,"Domain3D")==0) return Domain3DEnum;
     
    629643              else if (strcmp(name,"EffectivePressureTransient")==0) return EffectivePressureTransientEnum;
    630644              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;
    635646              else if (strcmp(name,"EplHead")==0) return EplHeadEnum;
    636647              else if (strcmp(name,"EplHeadOld")==0) return EplHeadOldEnum;
     
    741752              else if (strcmp(name,"Neumannflux")==0) return NeumannfluxEnum;
    742753              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;
    744758              else if (strcmp(name,"OmegaAbsGradient")==0) return OmegaAbsGradientEnum;
    745759              else if (strcmp(name,"OceantransportSpcbottompressure")==0) return OceantransportSpcbottompressureEnum;
     
    752766              else if (strcmp(name,"Radar")==0) return RadarEnum;
    753767              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;
    758769              else if (strcmp(name,"RadarIcePeriod")==0) return RadarIcePeriodEnum;
    759770              else if (strcmp(name,"RadarPowerMacGregor")==0) return RadarPowerMacGregorEnum;
     
    803814              else if (strcmp(name,"SealevelGrotm2")==0) return SealevelGrotm2Enum;
    804815              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;
    805825              else if (strcmp(name,"SealevelRSLBarystatic")==0) return SealevelRSLBarystaticEnum;
    806826              else if (strcmp(name,"SealevelRSLRate")==0) return SealevelRSLRateEnum;
     
    855875              else if (strcmp(name,"SmbD")==0) return SmbDEnum;
    856876              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;
    858881              else if (strcmp(name,"SmbDailydlradiation")==0) return SmbDailydlradiationEnum;
    859882              else if (strcmp(name,"SmbDailydsradiation")==0) return SmbDailydsradiationEnum;
     
    875898              else if (strcmp(name,"SmbEC")==0) return SmbECEnum;
    876899              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;
    881901              else if (strcmp(name,"SmbEla")==0) return SmbElaEnum;
    882902              else if (strcmp(name,"SmbEvaporation")==0) return SmbEvaporationEnum;
     
    978998              else if (strcmp(name,"SurfaceSlopeX")==0) return SurfaceSlopeXEnum;
    979999              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;
    9811004              else if (strcmp(name,"TemperaturePDD")==0) return TemperaturePDDEnum;
    9821005              else if (strcmp(name,"TemperaturePicard")==0) return TemperaturePicardEnum;
     
    9981021              else if (strcmp(name,"VxMesh")==0) return VxMeshEnum;
    9991022              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;
    10041024              else if (strcmp(name,"VxSurface")==0) return VxSurfaceEnum;
    10051025              else if (strcmp(name,"VyAverage")==0) return VyAverageEnum;
     
    11011121              else if (strcmp(name,"Outputdefinition78")==0) return Outputdefinition78Enum;
    11021122              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;
    11041127              else if (strcmp(name,"Outputdefinition80")==0) return Outputdefinition80Enum;
    11051128              else if (strcmp(name,"Outputdefinition81")==0) return Outputdefinition81Enum;
     
    11211144              else if (strcmp(name,"Outputdefinition96")==0) return Outputdefinition96Enum;
    11221145              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;
    11271147              else if (strcmp(name,"Outputdefinition99")==0) return Outputdefinition99Enum;
    11281148              else if (strcmp(name,"Outputdefinition9")==0) return Outputdefinition9Enum;
     
    12241244              else if (strcmp(name,"FileParam")==0) return FileParamEnum;
    12251245              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;
    12271250              else if (strcmp(name,"FloatingAreaScaled")==0) return FloatingAreaScaledEnum;
    12281251              else if (strcmp(name,"FloatingMeltRate")==0) return FloatingMeltRateEnum;
     
    12441267              else if (strcmp(name,"Gradient1")==0) return Gradient1Enum;
    12451268              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;
    12501270              else if (strcmp(name,"Gradient4")==0) return Gradient4Enum;
    12511271              else if (strcmp(name,"GroundedArea")==0) return GroundedAreaEnum;
     
    13471367              else if (strcmp(name,"MinVy")==0) return MinVyEnum;
    13481368              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;
    13501373              else if (strcmp(name,"Moulin")==0) return MoulinEnum;
    13511374              else if (strcmp(name,"MpiDense")==0) return MpiDenseEnum;
     
    13671390              else if (strcmp(name,"OceantransportSolution")==0) return OceantransportSolutionEnum;
    13681391              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;
    13731393              else if (strcmp(name,"Open")==0) return OpenEnum;
    13741394              else if (strcmp(name,"Option")==0) return OptionEnum;
     
    14701490              else if (strcmp(name,"ThicknessErrorEstimator")==0) return ThicknessErrorEstimatorEnum;
    14711491              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;
    14731496              else if (strcmp(name,"TotalFloatingBmb")==0) return TotalFloatingBmbEnum;
    14741497              else if (strcmp(name,"TotalFloatingBmbScaled")==0) return TotalFloatingBmbScaledEnum;
     
    14901513              else if (strcmp(name,"VertexSId")==0) return VertexSIdEnum;
    14911514              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;
    14961516              else if (strcmp(name,"Water")==0) return WaterEnum;
    14971517              else if (strcmp(name,"XTaylorHood")==0) return XTaylorHoodEnum;
  • issm/trunk-jpl/src/c/shared/Numerics/types.h

    r23357 r26242  
    1313
    1414#include <stdio.h>
     15#include <complex>
    1516
    1617/*here are our abstracted types: inspired on petsc */
     
    2425/*ADOLC typedefs*/
    2526#include "adolc/adolc.h"
    26 typedef adouble IssmDouble; /*for active variables*/
    27 typedef double  IssmPDouble; /*for passive variables*/
     27typedef adouble  IssmDouble; /*for active variables*/
     28typedef acomplex IssmComplex; /*for active variables*/
     29typedef double   IssmPDouble; /*for passive variables*/
     30typedef std::complex<double> IssmPComplex; /*for passive variables*/
    2831
    2932#elif defined(_HAVE_CODIPACK_) && !defined(_WRAPPERS_)
    3033/*CoDiPack typedefs*/
    3134#include <codi.hpp>
    32 typedef codi::RealReverse IssmDouble;
    33 typedef double            IssmPDouble;
     35typedef codi::RealReverse    IssmDouble;
     36//typedef codi::ComplexReverse IssmComplex; //not defined so far
     37typedef double               IssmPDouble;
     38typedef std::complex<double>  IssmPComplex;
    3439
    3540/*Non-AD typedefs*/
    3641#else
    37 typedef double     IssmDouble;
    38 typedef IssmDouble IssmPDouble;
     42typedef double              IssmDouble;
     43typedef std::complex<double> IssmComplex;
     44typedef IssmDouble          IssmPDouble;
     45typedef IssmComplex         IssmPComplex;
    3946#endif
    4047
  • issm/trunk-jpl/src/m/classes/fourierlove.m

    r26233 r26242  
    1919                istemporal                 = 0;
    2020                n_temporal_iterations      = 0;
    21                 time                       = 0;
     21                time                               = 0;
    2222                love_kernels               = 0;
    2323                forcing_type               = 0;
    24                 inner_core_boundary        = 0;
     24                inner_core_boundary            = 0;
    2525                core_mantle_boundary       = 0;
     26                complex_computation        = 0;
     27
    2628        end
    2729        methods (Static)
     
    6365                        self.inner_core_boundary=1;
    6466                        self.core_mantle_boundary=2;
     67                        self.complex_computation=0;
    6568                end % }}}
    6669                function disp(self) % {{{
     
    102105                        md = checkfield(md,'fieldname','love.love_kernels','values',[0 1]);
    103106                        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]);
    104108
    105109                        md = checkfield(md,'fieldname','love.istemporal','values',[0 1]);
     
    140144                        WriteData(fid,prefix,'object',self,'fieldname','istemporal','format','Boolean');
    141145                        WriteData(fid,prefix,'object',self,'fieldname','n_temporal_iterations','format','Integer');
     146                        WriteData(fid,prefix,'object',self,'fieldname','complex_computation','format','Boolean');
    142147                        %note: no need to marshall the time vector, we have frequencies
    143148                        WriteData(fid,prefix,'object',self,'fieldname','love_kernels','format','Boolean');
  • issm/trunk-jpl/src/m/solve/loadresultfromdisk.m

    r25300 r26242  
    4949                                        N=fread(fid,1,'int');
    5050                                        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);
    5156                                else
    5257                                        error(['cannot read data of type ' num2str(type) ]);
  • issm/trunk-jpl/test/NightlyRun/test2084.m

    r26235 r26242  
    2626md.materials.lame_lambda=md.materials.lame_mu*0+5e17;
    2727md.materials.issolid=[1 0 1 1 1 1]';
    28 md.materials.rheologymodel=2*ones(md.materials.numlayers,1);
     28md.materials.rheologymodel=0*ones(md.materials.numlayers,1);
    2929md.materials.burgers_mu=md.materials.lame_mu/3;
    3030md.materials.burgers_viscosity=md.materials.viscosity/10;
Note: See TracChangeset for help on using the changeset viewer.