Changeset 18834


Ignore:
Timestamp:
11/24/14 10:37:06 (10 years ago)
Author:
hongjuy
Message:

CHG: (1) adding support of inversion for 2D flowline model (2) adding support for inversion of RheologyB

File:
1 edited

Legend:

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

    r18771 r18834  
    337337
    338338        /*Intermediaries */
    339         int        num_responses,i,dim;
     339        int        num_responses,i,domaintype;
    340340        IssmDouble Jdet,obs_velocity_mag,velocity_mag;
    341341        IssmDouble vx,vy,vxobs,vyobs,dux,duy,weight;
     
    344344        IssmDouble *xyz_list_top = NULL;
    345345
    346         /*Get problem dimension*/
    347         element->FindParam(&dim,DomainDimensionEnum);
     346        /* Get domaintype*/
     347        element->FindParam(&domaintype,DomainTypeEnum);
    348348
    349349        /*Fetch number of nodes and dof for this finite element*/
     
    353353        /*Prepare coordinate system list*/
    354354        int* cs_list = xNew<int>(vnumnodes+pnumnodes);
    355         if(dim==2) for(i=0;i<vnumnodes;i++) cs_list[i] = XYEnum;
     355        if(domaintype==Domain2DverticalEnum) for(i=0;i<vnumnodes;i++) cs_list[i] = XYEnum;
    356356        else       for(i=0;i<vnumnodes;i++) cs_list[i] = XYZEnum;
    357357        for(i=0;i<pnumnodes;i++) cs_list[vnumnodes+i] = PressureEnum;
     
    367367        Input* weights_input = element->GetInput(InversionCostFunctionsCoefficientsEnum); _assert_(weights_input);
    368368        Input* vx_input      = element->GetInput(VxEnum);                                 _assert_(vx_input);
    369         Input* vy_input      = element->GetInput(VyEnum);                                 _assert_(vy_input);
    370369        Input* vxobs_input   = element->GetInput(InversionVxObsEnum);                     _assert_(vxobs_input);
    371         Input* vyobs_input   = element->GetInput(InversionVyObsEnum);                     _assert_(vyobs_input);
     370        Input* vy_input=NULL;
     371        Input* vyobs_input=NULL;
     372        if (domaintype!=Domain2DverticalEnum) {
     373                Input* vy_input      = element->GetInput(VyEnum);                                 _assert_(vy_input);
     374                Input* vyobs_input   = element->GetInput(InversionVyObsEnum);                     _assert_(vyobs_input);
     375        }
    372376        IssmDouble epsvel  = 2.220446049250313e-16;
    373377        IssmDouble meanvel = 3.170979198376458e-05; /*1000 m/yr*/
     
    389393
    390394                vx_input->GetInputValue(&vx,gauss);
    391                 vy_input->GetInputValue(&vy,gauss);
    392395                vxobs_input->GetInputValue(&vxobs,gauss);
    393                 vyobs_input->GetInputValue(&vyobs,gauss);
     396                if (domaintype!=Domain2DverticalEnum) {
     397                        vy_input->GetInputValue(&vy,gauss);
     398                        vyobs_input->GetInputValue(&vyobs,gauss);
     399                }
    394400
    395401                /*Loop over all requested responses*/
     
    409415                                         */
    410416                                        for(i=0;i<vnumnodes;i++){
    411                                                 dux=vxobs-vx;
    412                                                 pe->values[i*dim+0]+=dux*weight*Jdet*gauss->weight*vbasis[i];
    413                                                 if(dim==3){
     417                                                if(domaintype!=Domain2DverticalEnum){
     418                                                        dux=vxobs-vx;
     419                                                        pe->values[i*3+0]+=dux*weight*Jdet*gauss->weight*vbasis[i];
    414420                                                        duy=vyobs-vy;
    415                                                         pe->values[i*dim+1]+=duy*weight*Jdet*gauss->weight*vbasis[i];
     421                                                        pe->values[i*3+1]+=duy*weight*Jdet*gauss->weight*vbasis[i];
     422                                                }
     423                                                else{
     424                                                        dux=vxobs-vx;
     425                                                        pe->values[i*2+0]+=dux*weight*Jdet*gauss->weight*vbasis[i];
    416426                                                }
    417427                                        }
     
    430440                                         */
    431441                                        for(i=0;i<vnumnodes;i++){
    432                                                 scalex=pow(meanvel/(vxobs+epsvel),2); if(vxobs==0)scalex=0;
    433                                                 scaley=pow(meanvel/(vyobs+epsvel),2); if(vyobs==0)scaley=0;
    434                                                 dux=scalex*(vxobs-vx);
    435                                                 duy=scaley*(vyobs-vy);
    436                                                 pe->values[i*dim+0]+=dux*weight*Jdet*gauss->weight*vbasis[i];
    437                                                 pe->values[i*dim+1]+=duy*weight*Jdet*gauss->weight*vbasis[i];
     442                                                if(domaintype!=Domain2DverticalEnum){
     443                                                        scalex=pow(meanvel/(vxobs+epsvel),2); if(vxobs==0)scalex=0;
     444                                                        scaley=pow(meanvel/(vyobs+epsvel),2); if(vyobs==0)scaley=0;
     445                                                        dux=scalex*(vxobs-vx);
     446                                                        duy=scaley*(vyobs-vy);
     447                                                        pe->values[i*3+0]+=dux*weight*Jdet*gauss->weight*vbasis[i];
     448                                                        pe->values[i*3+1]+=duy*weight*Jdet*gauss->weight*vbasis[i];
     449                                                }
     450                                                else{
     451                                                        scalex=pow(meanvel/(vxobs+epsvel),2); if(vxobs==0)scalex=0;
     452                                                        dux=scalex*(vxobs-vx);
     453                                                        pe->values[i*2+0]+=dux*weight*Jdet*gauss->weight*vbasis[i];
     454                                                        pe->values[i*2+1]+=duy*weight*Jdet*gauss->weight*vbasis[i];
     455                                                }
    438456                                        }
    439457                                        break;
     
    451469                                         */
    452470                                        for(i=0;i<vnumnodes;i++){
    453                                                 if(dim==3){
     471                                                if(domaintype!=Domain2DverticalEnum){
    454472                                                        velocity_mag    =sqrt(vx*vx+vy*vy)+epsvel;
    455473                                                        obs_velocity_mag=sqrt(vxobs*vxobs+vyobs*vyobs)+epsvel;
     
    457475                                                        dux=scale*vx;
    458476                                                        duy=scale*vy;
    459                                                         pe->values[i*dim+0]+=dux*weight*Jdet*gauss->weight*vbasis[i];
    460                                                         pe->values[i*dim+1]+=duy*weight*Jdet*gauss->weight*vbasis[i];
     477                                                        pe->values[i*3+0]+=dux*weight*Jdet*gauss->weight*vbasis[i];
     478                                                        pe->values[i*3+1]+=duy*weight*Jdet*gauss->weight*vbasis[i];
    461479                                                }
    462480                                                else{
     
    465483                                                        scale=-8.*meanvel*meanvel/(velocity_mag*velocity_mag)*log(velocity_mag/obs_velocity_mag);
    466484                                                        dux=scale*vx;
    467                                                         pe->values[i*dim+0]+=dux*weight*Jdet*gauss->weight*vbasis[i];
     485                                                        pe->values[i*2+0]+=dux*weight*Jdet*gauss->weight*vbasis[i];
    468486                                                }
    469487                                        }
     
    480498                                         */
    481499                                        for(i=0;i<vnumnodes;i++){
    482                                                 scale=1./(S*2*sqrt(pow(vx-vxobs,2)+pow(vy-vyobs,2))+epsvel);
    483                                                 dux=scale*(vxobs-vx);
    484                                                 duy=scale*(vyobs-vy);
    485                                                 pe->values[i*dim+0]+=dux*weight*Jdet*gauss->weight*vbasis[i];
    486                                                 pe->values[i*dim+1]+=duy*weight*Jdet*gauss->weight*vbasis[i];
     500                                                if (domaintype!=Domain2DverticalEnum){
     501                                                        scale=1./(S*2*sqrt(pow(vx-vxobs,2)+pow(vy-vyobs,2))+epsvel);
     502                                                        dux=scale*(vxobs-vx);
     503                                                        duy=scale*(vyobs-vy);
     504                                                        pe->values[i*3+0]+=dux*weight*Jdet*gauss->weight*vbasis[i];
     505                                                        pe->values[i*3+1]+=duy*weight*Jdet*gauss->weight*vbasis[i];
     506                                                }
     507                                                else{
     508                                                        scale=1./(S*2*fabs(vx-vxobs)+epsvel);
     509                                                        dux=scale*(vxobs-vx);
     510                                                        pe->values[i*2+0]+=dux*weight*Jdet*gauss->weight*vbasis[i];
     511                                                }
    487512                                        }
    488513                                        break;
     
    498523                                         */
    499524                                        for(i=0;i<vnumnodes;i++){
    500                                                 dux = - meanvel*meanvel * log((fabs(vx)+epsvel)/(fabs(vxobs)+epsvel)) / (vx+epsvel);
    501                                                 duy = - meanvel*meanvel * log((fabs(vy)+epsvel)/(fabs(vyobs)+epsvel)) / (vy+epsvel);
    502                                                 pe->values[i*dim+0]+=dux*weight*Jdet*gauss->weight*vbasis[i];
    503                                                 pe->values[i*dim+1]+=duy*weight*Jdet*gauss->weight*vbasis[i];
     525                                                if(domaintype!=Domain2DverticalEnum){
     526                                                        dux = - meanvel*meanvel * log((fabs(vx)+epsvel)/(fabs(vxobs)+epsvel)) / (vx+epsvel);
     527                                                        duy = - meanvel*meanvel * log((fabs(vy)+epsvel)/(fabs(vyobs)+epsvel)) / (vy+epsvel);
     528                                                        pe->values[i*3+0]+=dux*weight*Jdet*gauss->weight*vbasis[i];
     529                                                        pe->values[i*3+1]+=duy*weight*Jdet*gauss->weight*vbasis[i];
     530                                                }
     531                                                else{
     532                                                        dux = - meanvel*meanvel * log((fabs(vx)+epsvel)/(fabs(vxobs)+epsvel)) / (vx+epsvel);
     533                                                        pe->values[i*2+0]+=dux*weight*Jdet*gauss->weight*vbasis[i];
     534                                                }
    504535                                        }
    505536                                        break;
     
    542573
    543574        /*Intermediaries */
    544         int        num_responses,i;
     575        int        num_responses,i,domaintype;
    545576        IssmDouble Jdet,obs_velocity_mag,velocity_mag;
    546577        IssmDouble vx,vy,vxobs,vyobs,dux,duy,weight;
     
    548579        int        *responses    = NULL;
    549580        IssmDouble *xyz_list_top = NULL;
     581
     582        /* Get domaintype*/
     583        element->FindParam(&domaintype,DomainTypeEnum);
    550584
    551585        /*Fetch number of nodes and dof for this finite element*/
     
    562596        Input* weights_input = element->GetInput(InversionCostFunctionsCoefficientsEnum); _assert_(weights_input);
    563597        Input* vx_input      = element->GetInput(VxEnum);                                 _assert_(vx_input);
    564         Input* vy_input      = element->GetInput(VyEnum);                                 _assert_(vy_input);
    565598        Input* vxobs_input   = element->GetInput(InversionVxObsEnum);                     _assert_(vxobs_input);
    566         Input* vyobs_input   = element->GetInput(InversionVyObsEnum);                     _assert_(vyobs_input);
     599        Input* vy_input=NULL;
     600        Input* vyobs_input=NULL;
     601        if(domaintype!=Domain2DverticalEnum){
     602                vy_input      = element->GetInput(VyEnum);                                 _assert_(vy_input);
     603                vyobs_input   = element->GetInput(InversionVyObsEnum);                     _assert_(vyobs_input);
     604        }
    567605        IssmDouble epsvel  = 2.220446049250313e-16;
    568606        IssmDouble meanvel = 3.170979198376458e-05; /*1000 m/yr*/
     
    584622
    585623                vx_input->GetInputValue(&vx,gauss);
    586                 vy_input->GetInputValue(&vy,gauss);
    587624                vxobs_input->GetInputValue(&vxobs,gauss);
    588                 vyobs_input->GetInputValue(&vyobs,gauss);
    589 
     625                if(domaintype!=Domain2DverticalEnum){
     626                        vy_input->GetInputValue(&vy,gauss);
     627                        vyobs_input->GetInputValue(&vyobs,gauss);
     628                }
    590629                /*Loop over all requested responses*/
    591630                for(int resp=0;resp<num_responses;resp++){
     
    604643                                         */
    605644                                        for(i=0;i<numnodes;i++){
    606                                                 dux=vxobs-vx;
    607                                                 duy=vyobs-vy;
    608                                                 pe->values[i*2+0]+=dux*weight*Jdet*gauss->weight*basis[i];
    609                                                 pe->values[i*2+1]+=duy*weight*Jdet*gauss->weight*basis[i];
     645                                                if(domaintype!=Domain2DverticalEnum){
     646                                                        dux=vxobs-vx;
     647                                                        duy=vyobs-vy;
     648                                                        pe->values[i*2+0]+=dux*weight*Jdet*gauss->weight*basis[i];
     649                                                        pe->values[i*2+1]+=duy*weight*Jdet*gauss->weight*basis[i];
     650                                                }
     651                                                else{
     652                                                        dux=vxobs-vx;
     653                                                        pe->values[i]+=dux*weight*Jdet*gauss->weight*basis[i];
     654                                                }
    610655                                        }
    611656                                        break;
     
    623668                                         */
    624669                                        for(i=0;i<numnodes;i++){
    625                                                 scalex=pow(meanvel/(vxobs+epsvel),2); if(vxobs==0)scalex=0;
    626                                                 scaley=pow(meanvel/(vyobs+epsvel),2); if(vyobs==0)scaley=0;
    627                                                 dux=scalex*(vxobs-vx);
    628                                                 duy=scaley*(vyobs-vy);
    629                                                 pe->values[i*2+0]+=dux*weight*Jdet*gauss->weight*basis[i];
    630                                                 pe->values[i*2+1]+=duy*weight*Jdet*gauss->weight*basis[i];
     670                                                if(domaintype!=Domain2DverticalEnum){
     671                                                        scalex=pow(meanvel/(vxobs+epsvel),2); if(vxobs==0)scalex=0;
     672                                                        scaley=pow(meanvel/(vyobs+epsvel),2); if(vyobs==0)scaley=0;
     673                                                        dux=scalex*(vxobs-vx);
     674                                                        duy=scaley*(vyobs-vy);
     675                                                        pe->values[i*2+0]+=dux*weight*Jdet*gauss->weight*basis[i];
     676                                                        pe->values[i*2+1]+=duy*weight*Jdet*gauss->weight*basis[i];
     677                                                }
     678                                                else{
     679                                                        scalex=pow(meanvel/(vxobs+epsvel),2); if(vxobs==0)scalex=0;
     680                                                        dux=scalex*(vxobs-vx);
     681                                                        pe->values[i]+=dux*weight*Jdet*gauss->weight*basis[i];
     682                                                }
    631683                                        }
    632684                                        break;
     
    644696                                         */
    645697                                        for(i=0;i<numnodes;i++){
    646                                                 velocity_mag    =sqrt(pow(vx,   2)+pow(vy,   2))+epsvel;
    647                                                 obs_velocity_mag=sqrt(pow(vxobs,2)+pow(vyobs,2))+epsvel;
    648                                                 scale=-8*pow(meanvel,2)/pow(velocity_mag,2)*log(velocity_mag/obs_velocity_mag);
    649                                                 dux=scale*vx;
    650                                                 duy=scale*vy;
    651                                                 pe->values[i*2+0]+=dux*weight*Jdet*gauss->weight*basis[i];
    652                                                 pe->values[i*2+1]+=duy*weight*Jdet*gauss->weight*basis[i];
     698                                                if(domaintype!=Domain2DverticalEnum){
     699                                                        velocity_mag    =sqrt(pow(vx,   2)+pow(vy,   2))+epsvel;
     700                                                        obs_velocity_mag=sqrt(pow(vxobs,2)+pow(vyobs,2))+epsvel;
     701                                                        scale=-8*pow(meanvel,2)/pow(velocity_mag,2)*log(velocity_mag/obs_velocity_mag);
     702                                                        dux=scale*vx;
     703                                                        duy=scale*vy;
     704                                                        pe->values[i*2+0]+=dux*weight*Jdet*gauss->weight*basis[i];
     705                                                        pe->values[i*2+1]+=duy*weight*Jdet*gauss->weight*basis[i];
     706                                                }
     707                                                else{
     708                                                        velocity_mag    =fabs(vx)+epsvel;
     709                                                        obs_velocity_mag=fabs(vxobs)+epsvel;
     710                                                        scale=-8*pow(meanvel,2)/pow(velocity_mag,2)*log(velocity_mag/obs_velocity_mag);
     711                                                        dux=scale*vx;
     712                                                        pe->values[i]+=dux*weight*Jdet*gauss->weight*basis[i];
     713                                                }
    653714                                        }
    654715                                        break;
     
    664725                                         */
    665726                                        for(i=0;i<numnodes;i++){
    666                                                 scale=1./(S*2*sqrt(pow(vx-vxobs,2)+pow(vy-vyobs,2))+epsvel);
    667                                                 dux=scale*(vxobs-vx);
    668                                                 duy=scale*(vyobs-vy);
    669                                                 pe->values[i*2+0]+=dux*weight*Jdet*gauss->weight*basis[i];
    670                                                 pe->values[i*2+1]+=duy*weight*Jdet*gauss->weight*basis[i];
     727                                                if(domaintype!=Domain2DverticalEnum){
     728                                                        scale=1./(S*2*sqrt(pow(vx-vxobs,2)+pow(vy-vyobs,2))+epsvel);
     729                                                        dux=scale*(vxobs-vx);
     730                                                        duy=scale*(vyobs-vy);
     731                                                        pe->values[i*2+0]+=dux*weight*Jdet*gauss->weight*basis[i];
     732                                                        pe->values[i*2+1]+=duy*weight*Jdet*gauss->weight*basis[i];
     733                                                }
     734                                                else{
     735                                                        scale=1./(S*2*fabs(vx-vxobs)+epsvel);
     736                                                        dux=scale*(vxobs-vx);
     737                                                        pe->values[i]+=dux*weight*Jdet*gauss->weight*basis[i];
     738                                                }
    671739                                        }
    672740                                        break;
     
    682750                                         */
    683751                                        for(i=0;i<numnodes;i++){
    684                                                 dux = - meanvel*meanvel * log((fabs(vx)+epsvel)/(fabs(vxobs)+epsvel)) / (vx+epsvel);
    685                                                 duy = - meanvel*meanvel * log((fabs(vy)+epsvel)/(fabs(vyobs)+epsvel)) / (vy+epsvel);
    686                                                 pe->values[i*2+0]+=dux*weight*Jdet*gauss->weight*basis[i];
    687                                                 pe->values[i*2+1]+=duy*weight*Jdet*gauss->weight*basis[i];
     752                                                if(domaintype!=Domain2DverticalEnum){
     753                                                        dux = - meanvel*meanvel * log((fabs(vx)+epsvel)/(fabs(vxobs)+epsvel)) / (vx+epsvel);
     754                                                        duy = - meanvel*meanvel * log((fabs(vy)+epsvel)/(fabs(vyobs)+epsvel)) / (vy+epsvel);
     755                                                        pe->values[i*2+0]+=dux*weight*Jdet*gauss->weight*basis[i];
     756                                                        pe->values[i*2+1]+=duy*weight*Jdet*gauss->weight*basis[i];
     757                                                }
     758                                                else{
     759                                                        dux = - meanvel*meanvel * log((fabs(vx)+epsvel)/(fabs(vxobs)+epsvel)) / (vx+epsvel);
     760                                                        pe->values[i]+=dux*weight*Jdet*gauss->weight*basis[i];
     761                                                }
    688762                                        }
    689763                                        break;
     
    701775                                        break;
    702776                                case RheologyBbarAbsGradientEnum:
     777                                        /*Nothing in P vector*/
     778                                        break;
     779                                case RheologyBAbsGradientEnum:
    703780                                        /*Nothing in P vector*/
    704781                                        break;
     
    710787
    711788        /*Transform coordinate system*/
    712         element->TransformLoadVectorCoord(pe,XYEnum);
     789        if(domaintype!=Domain2DverticalEnum) element->TransformLoadVectorCoord(pe,XYEnum);
    713790
    714791        /*Clean up and return*/
     
    731808                case Domain2DhorizontalEnum:
    732809                        basalelement = element;
     810                        break;
     811                case Domain2DverticalEnum:
     812                        if(!element->IsOnBase()) return NULL;
     813                        basalelement = element->SpawnBasalElement();
    733814                        break;
    734815                case Domain3DEnum:
     
    760841        Input* weights_input = basalelement->GetInput(InversionCostFunctionsCoefficientsEnum); _assert_(weights_input);
    761842        Input* vx_input      = basalelement->GetInput(VxEnum);                                 _assert_(vx_input);
    762         Input* vy_input      = basalelement->GetInput(VyEnum);                                 _assert_(vy_input);
    763843        Input* vxobs_input   = basalelement->GetInput(InversionVxObsEnum);                     _assert_(vxobs_input);
    764         Input* vyobs_input   = basalelement->GetInput(InversionVyObsEnum);                     _assert_(vyobs_input);
     844        Input* vy_input=NULL;
     845        Input* vyobs_input=NULL;
     846        if(domaintype!=Domain2DverticalEnum){
     847                vy_input      = basalelement->GetInput(VyEnum);                                 _assert_(vy_input);
     848                vyobs_input   = basalelement->GetInput(InversionVyObsEnum);                     _assert_(vyobs_input);
     849        }
    765850        IssmDouble epsvel  = 2.220446049250313e-16;
    766851        IssmDouble meanvel = 3.170979198376458e-05; /*1000 m/yr*/
     
    782867
    783868                vx_input->GetInputValue(&vx,gauss);
    784                 vy_input->GetInputValue(&vy,gauss);
    785869                vxobs_input->GetInputValue(&vxobs,gauss);
    786                 vyobs_input->GetInputValue(&vyobs,gauss);
    787 
     870                if(domaintype!=Domain2DverticalEnum){
     871                        vy_input->GetInputValue(&vy,gauss);
     872                        vyobs_input->GetInputValue(&vyobs,gauss);
     873                }
    788874                /*Loop over all requested responses*/
    789875                for(int resp=0;resp<num_responses;resp++){
     
    802888                                         */
    803889                                        for(i=0;i<numnodes;i++){
    804                                                 dux=vxobs-vx;
    805                                                 duy=vyobs-vy;
    806                                                 pe->values[i*2+0]+=dux*weight*Jdet*gauss->weight*basis[i];
    807                                                 pe->values[i*2+1]+=duy*weight*Jdet*gauss->weight*basis[i];
     890                                                if(domaintype!=Domain2DverticalEnum){
     891                                                        dux=vxobs-vx;
     892                                                        duy=vyobs-vy;
     893                                                        pe->values[i*2+0]+=dux*weight*Jdet*gauss->weight*basis[i];
     894                                                        pe->values[i*2+1]+=duy*weight*Jdet*gauss->weight*basis[i];
     895                                                }
     896                                                else {
     897                                                        dux=vxobs-vx;
     898                                                        pe->values[i]+=dux*weight*Jdet*gauss->weight*basis[i];
     899                                                }
    808900                                        }
    809901                                        break;
     
    821913                                         */
    822914                                        for(i=0;i<numnodes;i++){
    823                                                 scalex=pow(meanvel/(vxobs+epsvel),2); if(vxobs==0)scalex=0;
    824                                                 scaley=pow(meanvel/(vyobs+epsvel),2); if(vyobs==0)scaley=0;
    825                                                 dux=scalex*(vxobs-vx);
    826                                                 duy=scaley*(vyobs-vy);
    827                                                 pe->values[i*2+0]+=dux*weight*Jdet*gauss->weight*basis[i];
    828                                                 pe->values[i*2+1]+=duy*weight*Jdet*gauss->weight*basis[i];
     915                                                if(domaintype!=Domain2DverticalEnum){
     916                                                        scalex=pow(meanvel/(vxobs+epsvel),2); if(vxobs==0)scalex=0;
     917                                                        scaley=pow(meanvel/(vyobs+epsvel),2); if(vyobs==0)scaley=0;
     918                                                        dux=scalex*(vxobs-vx);
     919                                                        duy=scaley*(vyobs-vy);
     920                                                        pe->values[i*2+0]+=dux*weight*Jdet*gauss->weight*basis[i];
     921                                                        pe->values[i*2+1]+=duy*weight*Jdet*gauss->weight*basis[i];
     922                                                }
     923                                                else{
     924                                                        scalex=pow(meanvel/(vxobs+epsvel),2); if(vxobs==0)scalex=0;
     925                                                        dux=scalex*(vxobs-vx);
     926                                                        pe->values[i]+=dux*weight*Jdet*gauss->weight*basis[i];
     927                                                }
    829928                                        }
    830929                                        break;
     
    842941                                         */
    843942                                        for(i=0;i<numnodes;i++){
    844                                                 velocity_mag    =sqrt(pow(vx,   2)+pow(vy,   2))+epsvel;
    845                                                 obs_velocity_mag=sqrt(pow(vxobs,2)+pow(vyobs,2))+epsvel;
    846                                                 scale=-8*pow(meanvel,2)/pow(velocity_mag,2)*log(velocity_mag/obs_velocity_mag);
    847                                                 dux=scale*vx;
    848                                                 duy=scale*vy;
    849                                                 pe->values[i*2+0]+=dux*weight*Jdet*gauss->weight*basis[i];
    850                                                 pe->values[i*2+1]+=duy*weight*Jdet*gauss->weight*basis[i];
     943                                                if(domaintype!=Domain2DverticalEnum){
     944                                                        velocity_mag    =sqrt(pow(vx,   2)+pow(vy,   2))+epsvel;
     945                                                        obs_velocity_mag=sqrt(pow(vxobs,2)+pow(vyobs,2))+epsvel;
     946                                                        scale=-8*pow(meanvel,2)/pow(velocity_mag,2)*log(velocity_mag/obs_velocity_mag);
     947                                                        dux=scale*vx;
     948                                                        duy=scale*vy;
     949                                                        pe->values[i*2+0]+=dux*weight*Jdet*gauss->weight*basis[i];
     950                                                        pe->values[i*2+1]+=duy*weight*Jdet*gauss->weight*basis[i];
     951                                                }
     952                                                else{
     953                                                        velocity_mag    =fabs(vx)+epsvel;
     954                                                        obs_velocity_mag=fabs(vxobs)+epsvel;
     955                                                        scale=-8*pow(meanvel,2)/pow(velocity_mag,2)*log(velocity_mag/obs_velocity_mag);
     956                                                        dux=scale*vx;
     957                                                        pe->values[i]+=dux*weight*Jdet*gauss->weight*basis[i];
     958                                                }
    851959                                        }
    852960                                        break;
     
    862970                                         */
    863971                                        for(i=0;i<numnodes;i++){
    864                                                 scale=1./(S*2*sqrt(pow(vx-vxobs,2)+pow(vy-vyobs,2))+epsvel);
    865                                                 dux=scale*(vxobs-vx);
    866                                                 duy=scale*(vyobs-vy);
    867                                                 pe->values[i*2+0]+=dux*weight*Jdet*gauss->weight*basis[i];
    868                                                 pe->values[i*2+1]+=duy*weight*Jdet*gauss->weight*basis[i];
     972                                                if(domaintype!=Domain2DverticalEnum){
     973                                                        scale=1./(S*2*sqrt(pow(vx-vxobs,2)+pow(vy-vyobs,2))+epsvel);
     974                                                        dux=scale*(vxobs-vx);
     975                                                        duy=scale*(vyobs-vy);
     976                                                        pe->values[i*2+0]+=dux*weight*Jdet*gauss->weight*basis[i];
     977                                                        pe->values[i*2+1]+=duy*weight*Jdet*gauss->weight*basis[i];
     978                                                }
     979                                                else{
     980                                                        scale=1./(S*2*fabs(vx-vxobs)+epsvel);
     981                                                        dux=scale*(vxobs-vx);
     982                                                        pe->values[i]+=dux*weight*Jdet*gauss->weight*basis[i];
     983                                                }
    869984                                        }
    870985                                        break;
     
    880995                                         */
    881996                                        for(i=0;i<numnodes;i++){
    882                                                 dux = - meanvel*meanvel * log((fabs(vx)+epsvel)/(fabs(vxobs)+epsvel)) / (vx+epsvel);
    883                                                 duy = - meanvel*meanvel * log((fabs(vy)+epsvel)/(fabs(vyobs)+epsvel)) / (vy+epsvel);
    884                                                 pe->values[i*2+0]+=dux*weight*Jdet*gauss->weight*basis[i];
    885                                                 pe->values[i*2+1]+=duy*weight*Jdet*gauss->weight*basis[i];
     997                                                if(domaintype!=Domain2DverticalEnum){
     998                                                        dux = - meanvel*meanvel * log((fabs(vx)+epsvel)/(fabs(vxobs)+epsvel)) / (vx+epsvel);
     999                                                        duy = - meanvel*meanvel * log((fabs(vy)+epsvel)/(fabs(vyobs)+epsvel)) / (vy+epsvel);
     1000                                                        pe->values[i*2+0]+=dux*weight*Jdet*gauss->weight*basis[i];
     1001                                                        pe->values[i*2+1]+=duy*weight*Jdet*gauss->weight*basis[i];
     1002                                                }
     1003                                                else{
     1004                                                        dux = - meanvel*meanvel * log((fabs(vx)+epsvel)/(fabs(vxobs)+epsvel)) / (vx+epsvel);
     1005                                                        pe->values[i]+=dux*weight*Jdet*gauss->weight*basis[i];
     1006                                                }
    8861007                                        }
    8871008                                        break;
     
    8991020                                        break;
    9001021                                case RheologyBbarAbsGradientEnum:
     1022                                        /*Nothing in P vector*/
     1023                                        break;
     1024                                case RheologyBAbsGradientEnum:
    9011025                                        /*Nothing in P vector*/
    9021026                                        break;
     
    9081032
    9091033        /*Transform coordinate system*/
    910         basalelement->TransformLoadVectorCoord(pe,XYEnum);
     1034        if(domaintype!=Domain2DverticalEnum)    basalelement->TransformLoadVectorCoord(pe,XYEnum);
    9111035
    9121036        /*Clean up and return*/
     
    9511075        if(control_type!=MaterialsRheologyBbarEnum &&
    9521076                control_type!=FrictionCoefficientEnum   &&
    953                 control_type!=DamageDbarEnum){
     1077                control_type!=DamageDbarEnum            &&
     1078                control_type!=MaterialsRheologyBEnum){
    9541079                _error_("Control "<<EnumToStringx(control_type)<<" not supported");
    9551080        }
     
    9631088                case SurfaceAverageVelMisfitEnum: /*Nothing, \partial J/\partial k = 0*/ break;
    9641089                case DragCoefficientAbsGradientEnum: GradientJDragGradient(element,gradient,control_index); break;
    965                 case RheologyBbarAbsGradientEnum:    GradientJBGradient(element,gradient,control_index);    break;
     1090                case RheologyBbarAbsGradientEnum:    GradientJBbarGradient(element,gradient,control_index); break;
     1091                case RheologyBAbsGradientEnum:       GradientJBGradient(element,gradient,control_index);    break;
    9661092                default: _error_("response " << EnumToStringx(responses[resp]) << " not supported yet");
    9671093        }
     
    9891115                        }
    9901116                        break;
     1117                case MaterialsRheologyBEnum:
     1118                        switch(approximation){
     1119                                case SSAApproximationEnum: GradientJBSSA(element,gradient,control_index); break;
     1120                                case HOApproximationEnum:  GradientJBHO( element,gradient,control_index); break;
     1121                                case FSApproximationEnum:  GradientJBFS( element,gradient,control_index); break;
     1122                                case NoneApproximationEnum: /*Gradient is 0*/                    break;
     1123                                default: _error_("approximation " << EnumToStringx(approximation) << " not supported yet");
     1124                        }
     1125                        break;
    9911126                case DamageDbarEnum:
    9921127                        switch(approximation){
     
    10851220
    10861221}/*}}}*/
    1087 void AdjointHorizAnalysis::GradientJBGradient(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
     1222void AdjointHorizAnalysis::GradientJBbarGradient(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
    10881223
    10891224        /*Intermediaries*/
    1090         int      domaintype,dim;
     1225        int      domaintype;
    10911226        Element* basalelement;
    10921227
     
    10961231                case Domain2DhorizontalEnum:
    10971232                        basalelement = element;
    1098                         dim          = 2;
    10991233                        break;
    11001234                case Domain2DverticalEnum:
    11011235                        if(!element->IsOnBase()) return;
    11021236                        basalelement = element->SpawnBasalElement();
    1103                         dim          = 1;
    11041237                        break;
    11051238                case Domain3DEnum:
    11061239                        if(!element->IsOnBase()) return;
    11071240                        basalelement = element->SpawnBasalElement();
    1108                         dim          = 2;
    11091241                        break;
    11101242                default: _error_("mesh "<<EnumToStringx(domaintype)<<" not supported yet");
     
    11441276                /*Build gradje_g_gaussian vector (actually -dJ/ddrag): */
    11451277                for(int i=0;i<numvertices;i++){
    1146                         if(dim==2){
     1278                        if(domaintype!=Domain2DverticalEnum){
    11471279                                ge[i]+=-weight*Jdet*gauss->weight*(dbasis[0*numvertices+i]*dk[0]+dbasis[1*numvertices+i]*dk[1]);
    11481280                        }
     
    11621294        delete gauss;
    11631295        if(domaintype!=Domain2DhorizontalEnum){basalelement->DeleteMaterials(); delete basalelement;};
     1296}/*}}}*/
     1297void AdjointHorizAnalysis::GradientJBGradient(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
     1298
     1299        /*Intermediaries*/
     1300        int      domaintype;
     1301
     1302        /*Get basal element*/
     1303        element->FindParam(&domaintype,DomainTypeEnum);
     1304        switch(domaintype){
     1305                case Domain2DhorizontalEnum:
     1306                        break;
     1307                case Domain2DverticalEnum:
     1308                        break;
     1309                case Domain3DEnum:
     1310                        break;
     1311                default: _error_("mesh "<<EnumToStringx(domaintype)<<" not supported yet");
     1312        }
     1313
     1314        /*Intermediaries*/
     1315        IssmDouble Jdet,weight;
     1316        IssmDouble dk[3];
     1317        IssmDouble *xyz_list= NULL;
     1318
     1319        /*Fetch number of vertices for this finite element*/
     1320        int numvertices = element->GetNumberOfVertices();
     1321
     1322        /*Initialize some vectors*/
     1323        IssmDouble* dbasis        = xNew<IssmDouble>(3*numvertices);
     1324        IssmDouble* ge            = xNewZeroInit<IssmDouble>(numvertices);
     1325        int*        vertexpidlist = xNew<int>(numvertices);
     1326
     1327        /*Retrieve all inputs we will be needing: */
     1328        element->GetVerticesCoordinates(&xyz_list);
     1329        element->GradientIndexing(&vertexpidlist[0],control_index);
     1330        Input* rheology_input = element->GetInput(MaterialsRheologyBEnum);              _assert_(rheology_input);
     1331        Input* weights_input   = element->GetInput(InversionCostFunctionsCoefficientsEnum); _assert_(weights_input);
     1332        /* Start  looping on the number of gaussian points: */
     1333        Gauss* gauss=element->NewGauss(2);
     1334        for(int ig=gauss->begin();ig<gauss->end();ig++){
     1335                gauss->GaussPoint(ig);
     1336                element->JacobianDeterminant(&Jdet,xyz_list,gauss);
     1337                element->NodalFunctionsP1Derivatives(dbasis,xyz_list,gauss);
     1338                weights_input->GetInputValue(&weight,gauss,RheologyBAbsGradientEnum);
     1339
     1340                /*Build alpha_complement_list: */
     1341                rheology_input->GetInputDerivativeValue(&dk[0],xyz_list,gauss);
     1342
     1343                /*Build gradje_g_gaussian vector (actually -dJ/ddrag): */
     1344                for(int i=0;i<numvertices;i++){
     1345                        if(domaintype!=Domain2DverticalEnum){
     1346                                ge[i]+=-weight*Jdet*gauss->weight*(dbasis[0*numvertices+i]*dk[0]+dbasis[1*numvertices+i]*dk[1]);
     1347                        }
     1348                        else{
     1349                                ge[i]+=-weight*Jdet*gauss->weight*(dbasis[0*numvertices+i]*dk[0]+dbasis[1*numvertices+i]*dk[1]+dbasis[2*numvertices+i]*dk[2]);
     1350                        }
     1351                        _assert_(!xIsNan<IssmDouble>(ge[i]));
     1352                }
     1353        }
     1354        gradient->SetValues(numvertices,vertexpidlist,ge,ADD_VAL);
     1355
     1356        /*Clean up and return*/
     1357        xDelete<IssmDouble>(xyz_list);
     1358        xDelete<IssmDouble>(dbasis);
     1359        xDelete<IssmDouble>(ge);
     1360        xDelete<int>(vertexpidlist);
     1361        delete gauss;
    11641362}/*}}}*/
    11651363void AdjointHorizAnalysis::GradientJDragSSA(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
     
    12631461
    12641462        /*Intermediaries*/
    1265         int        dim=3;
    12661463        IssmDouble Jdet,weight;
    12671464        IssmDouble drag,dalpha2dk;
     
    12691466        IssmDouble *xyz_list_base= NULL;
    12701467
     1468        int      domaintype,dim;
     1469        element->FindParam(&domaintype,DomainTypeEnum);
    12711470        /*Fetch number of vertices for this finite element*/
    12721471        int numvertices = element->GetNumberOfVertices();
     
    12781477
    12791478        /*Build friction element, needed later: */
     1479        if(domaintype!=Domain2DverticalEnum) dim=3;
     1480        else dim=2;
     1481        Friction* friction=new Friction(element,dim);
     1482
     1483        /*Retrieve all inputs we will be needing: */
     1484        element->GetVerticesCoordinatesBase(&xyz_list_base);
     1485        element->GradientIndexing(&vertexpidlist[0],control_index);
     1486        Input* vx_input        = element->GetInput(VxEnum);                   _assert_(vx_input);
     1487        Input* vy_input        = NULL;
     1488        Input* adjointx_input  = element->GetInput(AdjointxEnum);             _assert_(adjointx_input);
     1489        Input* adjointy_input  = NULL;
     1490        Input* dragcoeff_input = element->GetInput(FrictionCoefficientEnum);  _assert_(dragcoeff_input);
     1491        if(domaintype!=Domain2DverticalEnum){
     1492                vy_input        = element->GetInput(VyEnum);                   _assert_(vy_input);
     1493                adjointy_input  = element->GetInput(AdjointyEnum);             _assert_(adjointy_input);
     1494        }
     1495        /* Start  looping on the number of gaussian points: */
     1496        Gauss* gauss=element->NewGaussBase(4);
     1497        for(int ig=gauss->begin();ig<gauss->end();ig++){
     1498                gauss->GaussPoint(ig);
     1499
     1500                adjointx_input->GetInputValue(&lambda, gauss);
     1501                vx_input->GetInputValue(&vx,gauss);
     1502                if(domaintype!=Domain2DverticalEnum){
     1503                        adjointy_input->GetInputValue(&mu, gauss);
     1504                        vy_input->GetInputValue(&vy,gauss);
     1505                }
     1506                dragcoeff_input->GetInputValue(&drag, gauss);
     1507
     1508                friction->GetAlphaComplement(&dalpha2dk,gauss);
     1509
     1510                element->JacobianDeterminantBase(&Jdet,xyz_list_base,gauss);
     1511                element->NodalFunctionsP1(basis,gauss);
     1512
     1513                /*Build gradient vector (actually -dJ/dD): */
     1514                for(int i=0;i<numvertices;i++){
     1515                        if(domaintype!=Domain2DverticalEnum) ge[i]+=-2.*drag*dalpha2dk*((lambda*vx+mu*vy))*Jdet*gauss->weight*basis[i];
     1516                        else ge[i]+=-2.*drag*dalpha2dk*(lambda*vx)*Jdet*gauss->weight*basis[i];
     1517                        _assert_(!xIsNan<IssmDouble>(ge[i]));
     1518                }
     1519        }
     1520        gradient->SetValues(numvertices,vertexpidlist,ge,ADD_VAL);
     1521
     1522        /*Clean up and return*/
     1523        xDelete<IssmDouble>(xyz_list_base);
     1524        xDelete<IssmDouble>(basis);
     1525        xDelete<IssmDouble>(ge);
     1526        xDelete<int>(vertexpidlist);
     1527        delete gauss;
     1528        delete friction;
     1529}/*}}}*/
     1530void AdjointHorizAnalysis::GradientJDragFS(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
     1531
     1532        /*return if floating or not on bed (gradient is 0)*/
     1533        if(element->IsFloating()) return;
     1534        if(!element->IsOnBase()) return;
     1535
     1536        /*Intermediaries*/
     1537        int        domaintype,dim;
     1538        IssmDouble Jdet,weight;
     1539        IssmDouble drag,dalpha2dk,normal[3];
     1540        IssmDouble vx,vy,vz,lambda,mu,xi;
     1541        IssmDouble *xyz_list_base= NULL;
     1542
     1543        /*Fetch number of vertices for this finite element*/
     1544        int numvertices = element->GetNumberOfVertices();
     1545
     1546        /*Initialize some vectors*/
     1547        IssmDouble* basis         = xNew<IssmDouble>(numvertices);
     1548        IssmDouble* ge            = xNewZeroInit<IssmDouble>(numvertices);
     1549        int*        vertexpidlist = xNew<int>(numvertices);
     1550
     1551        /* get domaintype */
     1552        element->FindParam(&domaintype,DomainTypeEnum);
     1553
     1554        /*Build friction element, needed later: */
     1555        if(domaintype!=Domain2DverticalEnum) dim=3;
     1556        else dim=2;
    12801557        Friction* friction=new Friction(element,dim);
    12811558
     
    12871564        Input* adjointx_input  = element->GetInput(AdjointxEnum);             _assert_(adjointx_input);
    12881565        Input* adjointy_input  = element->GetInput(AdjointyEnum);             _assert_(adjointy_input);
     1566        Input* vz_input        = NULL;
     1567        Input* adjointz_input  = NULL;
     1568        if(domaintype!=Domain2DverticalEnum){
     1569                Input* vz_input        = element->GetInput(VzEnum);                   _assert_(vy_input);
     1570                Input* adjointz_input  = element->GetInput(AdjointzEnum);             _assert_(adjointz_input);
     1571        }
    12891572        Input* dragcoeff_input = element->GetInput(FrictionCoefficientEnum);  _assert_(dragcoeff_input);
    12901573
     
    12981581                vx_input->GetInputValue(&vx,gauss);
    12991582                vy_input->GetInputValue(&vy,gauss);
     1583                if(domaintype!=Domain2DverticalEnum){
     1584                        adjointz_input->GetInputValue(&xi    ,gauss);
     1585                        vz_input->GetInputValue(&vz,gauss);
     1586                }
    13001587                dragcoeff_input->GetInputValue(&drag, gauss);
    13011588
    13021589                friction->GetAlphaComplement(&dalpha2dk,gauss);
     1590                element->NormalBase(&normal[0],xyz_list_base);
    13031591
    13041592                element->JacobianDeterminantBase(&Jdet,xyz_list_base,gauss);
    13051593                element->NodalFunctionsP1(basis,gauss);
    13061594
    1307                 /*Build gradient vector (actually -dJ/dD): */
    1308                 for(int i=0;i<numvertices;i++){
    1309                         ge[i]+=-2.*drag*dalpha2dk*((lambda*vx+mu*vy))*Jdet*gauss->weight*basis[i];
    1310                         _assert_(!xIsNan<IssmDouble>(ge[i]));
    1311                 }
    1312         }
    1313         gradient->SetValues(numvertices,vertexpidlist,ge,ADD_VAL);
    1314 
    1315         /*Clean up and return*/
    1316         xDelete<IssmDouble>(xyz_list_base);
    1317         xDelete<IssmDouble>(basis);
    1318         xDelete<IssmDouble>(ge);
    1319         xDelete<int>(vertexpidlist);
    1320         delete gauss;
    1321         delete friction;
    1322 }/*}}}*/
    1323 void AdjointHorizAnalysis::GradientJDragFS(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
    1324 
    1325         /*return if floating or not on bed (gradient is 0)*/
    1326         if(element->IsFloating()) return;
    1327         if(!element->IsOnBase()) return;
    1328 
    1329         /*Intermediaries*/
    1330         int        dim=3;
    1331         IssmDouble Jdet,weight;
    1332         IssmDouble drag,dalpha2dk,normal[3];
    1333         IssmDouble vx,vy,vz,lambda,mu,xi;
    1334         IssmDouble *xyz_list_base= NULL;
    1335 
    1336         /*Fetch number of vertices for this finite element*/
    1337         int numvertices = element->GetNumberOfVertices();
    1338 
    1339         /*Initialize some vectors*/
    1340         IssmDouble* basis         = xNew<IssmDouble>(numvertices);
    1341         IssmDouble* ge            = xNewZeroInit<IssmDouble>(numvertices);
    1342         int*        vertexpidlist = xNew<int>(numvertices);
    1343 
    1344         /*Build friction element, needed later: */
    1345         Friction* friction=new Friction(element,dim);
    1346 
    1347         /*Retrieve all inputs we will be needing: */
    1348         element->GetVerticesCoordinatesBase(&xyz_list_base);
    1349         element->GradientIndexing(&vertexpidlist[0],control_index);
    1350         Input* vx_input        = element->GetInput(VxEnum);                   _assert_(vx_input);
    1351         Input* vy_input        = element->GetInput(VyEnum);                   _assert_(vy_input);
    1352         Input* vz_input        = element->GetInput(VzEnum);                   _assert_(vy_input);
    1353         Input* adjointx_input  = element->GetInput(AdjointxEnum);             _assert_(adjointx_input);
    1354         Input* adjointy_input  = element->GetInput(AdjointyEnum);             _assert_(adjointy_input);
    1355         Input* adjointz_input  = element->GetInput(AdjointzEnum);             _assert_(adjointz_input);
    1356         Input* dragcoeff_input = element->GetInput(FrictionCoefficientEnum);  _assert_(dragcoeff_input);
    1357 
    1358         /* Start  looping on the number of gaussian points: */
    1359         Gauss* gauss=element->NewGaussBase(4);
    1360         for(int ig=gauss->begin();ig<gauss->end();ig++){
    1361                 gauss->GaussPoint(ig);
    1362 
    1363                 adjointx_input->GetInputValue(&lambda, gauss);
    1364                 adjointy_input->GetInputValue(&mu, gauss);
    1365                 adjointz_input->GetInputValue(&xi    ,gauss);
    1366                 vx_input->GetInputValue(&vx,gauss);
    1367                 vy_input->GetInputValue(&vy,gauss);
    1368                 vz_input->GetInputValue(&vz,gauss);
    1369                 dragcoeff_input->GetInputValue(&drag, gauss);
    1370 
    1371                 friction->GetAlphaComplement(&dalpha2dk,gauss);
    1372                 element->NormalBase(&normal[0],xyz_list_base);
    1373 
    1374                 element->JacobianDeterminantBase(&Jdet,xyz_list_base,gauss);
    1375                 element->NodalFunctionsP1(basis,gauss);
    1376 
    13771595                /*Build gradient vector (actually -dJ/dk): */
    1378                 for(int i=0;i<numvertices;i++){
    1379                         ge[i]+=(
    1380                                                 -lambda*(2*drag*dalpha2dk*(vx - vz*normal[0]*normal[2]))
    1381                                                 -mu    *(2*drag*dalpha2dk*(vy - vz*normal[1]*normal[2]))
    1382                                                 -xi    *(2*drag*dalpha2dk*(-vx*normal[0]*normal[2]-vy*normal[1]*normal[2]))
    1383                                                 )*Jdet*gauss->weight*basis[i];
    1384                         _assert_(!xIsNan<IssmDouble>(ge[i]));
     1596                if(domaintype!=Domain2DverticalEnum){
     1597                        for(int i=0;i<numvertices;i++){
     1598                                ge[i]+=(
     1599                                                        -lambda*(2*drag*dalpha2dk*(vx - vz*normal[0]*normal[2]))
     1600                                                        -mu    *(2*drag*dalpha2dk*(vy - vz*normal[1]*normal[2]))
     1601                                                        -xi    *(2*drag*dalpha2dk*(-vx*normal[0]*normal[2]-vy*normal[1]*normal[2]))
     1602                                                 )*Jdet*gauss->weight*basis[i];
     1603                                _assert_(!xIsNan<IssmDouble>(ge[i]));
     1604                        }
     1605                }
     1606                else{
     1607                        for(int i=0;i<numvertices;i++){
     1608                                ge[i]+=(
     1609                                                        -lambda*2*drag*dalpha2dk*vx
     1610                                                        -mu    *2*drag*dalpha2dk*vy
     1611                                                 )*Jdet*gauss->weight*basis[i];
     1612                                _assert_(!xIsNan<IssmDouble>(ge[i]));
     1613                        }
    13851614                }
    13861615        }
     
    14931722        this->GradientJBbarSSA(element,gradient,control_index);
    14941723}/*}}}*/
     1724void AdjointHorizAnalysis::GradientJBSSA(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
     1725
     1726        /*Intermediaries*/
     1727        int      domaintype,dim;
     1728        Element* basalelement;
     1729
     1730        /*Get basal element*/
     1731        element->FindParam(&domaintype,DomainTypeEnum);
     1732        switch(domaintype){
     1733                case Domain2DhorizontalEnum:
     1734                        basalelement = element;
     1735                        dim          = 2;
     1736                        break;
     1737                case Domain2DverticalEnum:
     1738                        if(!element->IsOnBase()) return;
     1739                        basalelement = element->SpawnBasalElement();
     1740                        dim          = 1;
     1741                        break;
     1742                case Domain3DEnum:
     1743                        if(!element->IsOnBase()) return;
     1744                        basalelement = element->SpawnBasalElement();
     1745                        dim          = 2;
     1746                        break;
     1747                default: _error_("mesh "<<EnumToStringx(domaintype)<<" not supported yet");
     1748        }
     1749
     1750        /*Intermediaries*/
     1751        IssmDouble Jdet,weight;
     1752        IssmDouble thickness,dmudB;
     1753        IssmDouble dvx[3],dvy[3],dadjx[3],dadjy[3];
     1754        IssmDouble *xyz_list= NULL;
     1755
     1756        /*Fetch number of vertices for this finite element*/
     1757        int numvertices = basalelement->GetNumberOfVertices();
     1758
     1759        /*Initialize some vectors*/
     1760        IssmDouble* basis         = xNew<IssmDouble>(numvertices);
     1761        IssmDouble* ge            = xNewZeroInit<IssmDouble>(numvertices);
     1762        int*        vertexpidlist = xNew<int>(numvertices);
     1763
     1764        /*Retrieve all inputs we will be needing: */
     1765        basalelement->GetVerticesCoordinates(&xyz_list);
     1766        basalelement->GradientIndexing(&vertexpidlist[0],control_index);
     1767        Input* thickness_input = basalelement->GetInput(ThicknessEnum);             _assert_(thickness_input);
     1768        Input* vx_input        = basalelement->GetInput(VxEnum);                    _assert_(vx_input);
     1769        Input* vy_input        = basalelement->GetInput(VyEnum);                    _assert_(vy_input);
     1770        Input* adjointx_input  = basalelement->GetInput(AdjointxEnum);              _assert_(adjointx_input);
     1771        Input* adjointy_input  = basalelement->GetInput(AdjointyEnum);              _assert_(adjointy_input);
     1772        Input* rheologyb_input = basalelement->GetInput(MaterialsRheologyBEnum); _assert_(rheologyb_input);
     1773
     1774        /* Start  looping on the number of gaussian points: */
     1775        Gauss* gauss=basalelement->NewGauss(4);
     1776        for(int ig=gauss->begin();ig<gauss->end();ig++){
     1777                gauss->GaussPoint(ig);
     1778
     1779                thickness_input->GetInputValue(&thickness,gauss);
     1780                vx_input->GetInputDerivativeValue(&dvx[0],xyz_list,gauss);
     1781                vy_input->GetInputDerivativeValue(&dvy[0],xyz_list,gauss);
     1782                adjointx_input->GetInputDerivativeValue(&dadjx[0],xyz_list,gauss);
     1783                adjointy_input->GetInputDerivativeValue(&dadjy[0],xyz_list,gauss);
     1784
     1785                basalelement->dViscositydBSSA(&dmudB,dim,xyz_list,gauss,vx_input,vy_input);
     1786
     1787                basalelement->JacobianDeterminant(&Jdet,xyz_list,gauss);
     1788                basalelement->NodalFunctionsP1(basis,gauss);
     1789
     1790                /*Build gradient vector (actually -dJ/dB): */
     1791                for(int i=0;i<numvertices;i++){
     1792                        ge[i]+=-dmudB*thickness*(
     1793                                                (2*dvx[0]+dvy[1])*2*dadjx[0]+(dvx[1]+dvy[0])*(dadjx[1]+dadjy[0])+(2*dvy[1]+dvx[0])*2*dadjy[1]
     1794                                                )*Jdet*gauss->weight*basis[i];
     1795                        _assert_(!xIsNan<IssmDouble>(ge[i]));
     1796                }
     1797        }
     1798        gradient->SetValues(numvertices,vertexpidlist,ge,ADD_VAL);
     1799
     1800        /*Clean up and return*/
     1801        xDelete<IssmDouble>(xyz_list);
     1802        xDelete<IssmDouble>(basis);
     1803        xDelete<IssmDouble>(ge);
     1804        xDelete<int>(vertexpidlist);
     1805        delete gauss;
     1806        if(domaintype!=Domain2DhorizontalEnum){basalelement->DeleteMaterials(); delete basalelement;};
     1807}/*}}}*/
     1808void AdjointHorizAnalysis::GradientJBHO(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
     1809        /*Intermediaries*/
     1810        int      domaintype,dim;
     1811
     1812        /*Get domaintype*/
     1813        element->FindParam(&domaintype,DomainTypeEnum);
     1814
     1815        /*Intermediaries*/
     1816        IssmDouble Jdet,weight;
     1817        IssmDouble thickness,dmudB;
     1818        IssmDouble dvx[3],dvy[3],dadjx[3],dadjy[3];
     1819        IssmDouble *xyz_list= NULL;
     1820
     1821        /*Fetch number of vertices for this finite element*/
     1822        int numvertices = element->GetNumberOfVertices();
     1823
     1824        /*Initialize some vectors*/
     1825        IssmDouble* basis         = xNew<IssmDouble>(numvertices);
     1826        IssmDouble* ge            = xNewZeroInit<IssmDouble>(numvertices);
     1827        int*        vertexpidlist = xNew<int>(numvertices);
     1828
     1829        /*Retrieve all inputs we will be needing: */
     1830        element->GetVerticesCoordinates(&xyz_list);
     1831        element->GradientIndexing(&vertexpidlist[0],control_index);
     1832        Input* thickness_input = element->GetInput(ThicknessEnum);             _assert_(thickness_input);
     1833        Input* vx_input        = element->GetInput(VxEnum);                    _assert_(vx_input);
     1834        Input* vy_input        = NULL;
     1835        Input* adjointx_input  = element->GetInput(AdjointxEnum);              _assert_(adjointx_input);
     1836        Input* adjointy_input  = NULL;
     1837        Input* rheologyb_input = element->GetInput(MaterialsRheologyBEnum); _assert_(rheologyb_input);
     1838        if(domaintype!=Domain2DverticalEnum){
     1839                vy_input        = element->GetInput(VyEnum);                   _assert_(vy_input);
     1840                adjointy_input  = element->GetInput(AdjointyEnum);             _assert_(adjointy_input);
     1841        }
     1842        /* Start  looping on the number of gaussian points: */
     1843        Gauss* gauss=element->NewGauss(4);
     1844        for(int ig=gauss->begin();ig<gauss->end();ig++){
     1845                gauss->GaussPoint(ig);
     1846
     1847                thickness_input->GetInputValue(&thickness,gauss);
     1848                vx_input->GetInputDerivativeValue(&dvx[0],xyz_list,gauss);
     1849                adjointx_input->GetInputDerivativeValue(&dadjx[0],xyz_list,gauss);
     1850                dim=2;
     1851                if(domaintype!=Domain2DverticalEnum){
     1852                        adjointy_input->GetInputDerivativeValue(&dadjy[0],xyz_list, gauss);
     1853                        vy_input->GetInputDerivativeValue(&dvy[0],xyz_list,gauss);
     1854                        dim=3;
     1855                }
     1856
     1857                element->dViscositydBHO(&dmudB,dim,xyz_list,gauss,vx_input,vy_input);
     1858
     1859                element->JacobianDeterminant(&Jdet,xyz_list,gauss);
     1860                element->NodalFunctionsP1(basis,gauss);
     1861
     1862                /*Build gradient vector (actually -dJ/dB): */
     1863                for(int i=0;i<numvertices;i++){
     1864                        if(domaintype!=Domain2DverticalEnum){
     1865                                ge[i]+=-dmudB*thickness*(
     1866                                                        (2*dvx[0]+dvy[1])*2*dadjx[0]+(dvx[1]+dvy[0])*(dadjx[1]+dadjy[0])+(2*dvy[1]+dvx[0])*2*dadjy[1]
     1867                                                        )*Jdet*gauss->weight*basis[i];
     1868                        }
     1869                        else{
     1870                                ge[i]+=-dmudB*thickness*4*dvx[0]*dadjx[0]*Jdet*gauss->weight*basis[i];
     1871                        }
     1872                        _assert_(!xIsNan<IssmDouble>(ge[i]));
     1873                }
     1874        }
     1875        gradient->SetValues(numvertices,vertexpidlist,ge,ADD_VAL);
     1876
     1877        /*Clean up and return*/
     1878        xDelete<IssmDouble>(xyz_list);
     1879        xDelete<IssmDouble>(basis);
     1880        xDelete<IssmDouble>(ge);
     1881        xDelete<int>(vertexpidlist);
     1882        delete gauss;
     1883}/*}}}*/
     1884void AdjointHorizAnalysis::GradientJBFS(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
     1885        /*WARNING: We use HO as an estimate for now*/
     1886        this->GradientJBHO(element,gradient,control_index);
     1887}/*}}}*/
    14951888void AdjointHorizAnalysis::GradientJDSSA(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
    14961889
     
    15901983        int* doflist=NULL;
    15911984
     1985        int    domaintype;
     1986        element->FindParam(&domaintype,DomainTypeEnum);
     1987
    15921988        /*Fetch number of nodes and dof for this finite element*/
    15931989        int numnodes = element->GetNumberOfNodes();
    1594         int numdof   = numnodes*2;
    1595 
     1990        int numdof;
     1991        if(domaintype!=Domain2DverticalEnum)  numdof   = numnodes*2;
     1992        else                                              numdof   = numnodes*1;
    15961993        /*Fetch dof list and allocate solution vectors*/
    15971994        element->GetDofList(&doflist,NoneApproximationEnum,GsetEnum);
     
    16042001
    16052002        /*Transform solution in Cartesian Space*/
    1606         element->TransformSolutionCoord(&values[0],XYEnum);
     2003        if(domaintype!=Domain2DverticalEnum)    element->TransformSolutionCoord(&values[0],XYEnum);
    16072004
    16082005        /*Ok, we have vx and vy in values, fill in vx and vy arrays: */
    16092006        for(i=0;i<numnodes;i++){
    1610                 lambdax[i]=values[i*NDOF2+0];
    1611                 lambday[i]=values[i*NDOF2+1];
    1612 
     2007                if(domaintype!=Domain2DverticalEnum){
     2008                        lambdax[i]=values[i*NDOF2+0];
     2009                        lambday[i]=values[i*NDOF2+1];
     2010                }
     2011                else {lambdax[i]=values[i];lambday[i]=0;}
    16132012                /*Check solution*/
    16142013                if(xIsNan<IssmDouble>(lambdax[i])) _error_("NaN found in solution vector");
    1615                 if(xIsNan<IssmDouble>(lambday[i])) _error_("NaN found in solution vector");
     2014                if(domaintype!=Domain2DverticalEnum && xIsNan<IssmDouble>(lambday[i])) _error_("NaN found in solution vector");
    16162015        }
    16172016
     
    16272026}/*}}}*/
    16282027void AdjointHorizAnalysis::InputUpdateFromSolutionFS(IssmDouble* solution,Element* element){/*{{{*/
    1629         int          i,dim;
     2028        int          i,fe_FS;
    16302029        int*         vdoflist=NULL;
    16312030        int*         pdoflist=NULL;
    16322031        IssmDouble   FSreconditioning;
    16332032
    1634         element->FindParam(&dim,DomainDimensionEnum);
     2033        int      domaintype,dim;
     2034        element->FindParam(&domaintype,DomainTypeEnum);
     2035        switch(domaintype){
     2036                case Domain2DhorizontalEnum:
     2037                        dim          = 3;
     2038                        break;
     2039                case Domain2DverticalEnum:
     2040                        dim          = 2;
     2041                        break;
     2042                case Domain3DEnum:
     2043                        dim          = 3;
     2044                        break;
     2045                default: _error_("mesh "<<EnumToStringx(domaintype)<<" not supported yet");
     2046        }
     2047
    16352048
    16362049        /*Fetch number of nodes and dof for this finite element*/
     
    16652078        /*fill in all arrays: */
    16662079        for(i=0;i<vnumnodes;i++){
    1667                 lambdax[i] = values[i*NDOF3+0]; if(xIsNan<IssmDouble>(lambdax[i])) _error_("NaN found in solution vector");
    1668                 lambday[i] = values[i*NDOF3+1]; if(xIsNan<IssmDouble>(lambday[i])) _error_("NaN found in solution vector");
    1669                 lambdaz[i] = values[i*NDOF3+2]; if(xIsNan<IssmDouble>(lambdaz[i])) _error_("NaN found in solution vector");
     2080                lambdax[i] = values[i*dim+0]; if(xIsNan<IssmDouble>(lambdax[i])) _error_("NaN found in solution vector");
     2081                lambday[i] = values[i*dim+1]; if(xIsNan<IssmDouble>(lambday[i])) _error_("NaN found in solution vector");
     2082                if(dim==3){
     2083                        lambdaz[i] = values[i*dim+2]; if(xIsNan<IssmDouble>(lambdaz[i])) _error_("NaN found in solution vector");
     2084                }
    16702085        }
    16712086        for(i=0;i<pnumnodes;i++){
     
    16802095        element->AddInput(AdjointxEnum,lambdax,element->VelocityInterpolation());
    16812096        element->AddInput(AdjointyEnum,lambday,element->VelocityInterpolation());
    1682         element->AddInput(AdjointzEnum,lambdaz,element->VelocityInterpolation());
    1683         element->AddInput(AdjointpEnum,lambdap,element->PressureInterpolation());
     2097        if(domaintype!=Domain2DverticalEnum) element->AddInput(AdjointzEnum,lambdaz,element->VelocityInterpolation());
     2098
     2099        element->FindParam(&fe_FS,FlowequationFeFSEnum);
     2100        if(fe_FS!=LATaylorHoodEnum && fe_FS!=LACrouzeixRaviartEnum)     
     2101         element->AddInput(AdjointpEnum,lambdap,element->PressureInterpolation());     
    16842102
    16852103        /*Free ressources:*/
Note: See TracChangeset for help on using the changeset viewer.