Ignore:
Timestamp:
05/26/14 11:22:52 (11 years ago)
Author:
Mathieu Morlighem
Message:

CHG: moving gradients from element to adjoint analyses

File:
1 edited

Legend:

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

    r18057 r18060  
    151151}/*}}}*/
    152152void AdjointBalancethicknessAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
    153         _error_("Not implemented yet");
     153        /*The gradient of the cost function is calculated in 2 parts.
     154         *
     155         * dJ    \partial J   \partial lambda^T(KU-F)
     156         * --  = ---------- + ------------------------
     157         * dk    \partial k   \parial k                 
     158         *
     159         * */
     160
     161        /*If on water, grad = 0: */
     162        if(!element->IsIceInElement()) return;
     163
     164        /*Get list of cost functions*/
     165        int *responses = NULL;
     166        int num_responses,resp;
     167        element->FindParam(&num_responses,InversionNumCostFunctionsEnum);
     168        element->FindParam(&responses,NULL,InversionCostFunctionsEnum);
     169
     170        /*Check that control_type is supported*/
     171        if(control_type!=VxEnum &&
     172                control_type!=VyEnum &&
     173                control_type!=BalancethicknessThickeningRateEnum){
     174                _error_("Control "<<EnumToStringx(control_type)<<" not supported");
     175        }
     176
     177        /*Deal with first part (partial derivative a J with respect to k)*/
     178        for(resp=0;resp<num_responses;resp++) switch(responses[resp]){
     179                case ThicknessAbsMisfitEnum:      /*Nothing, \partial J/\partial k = 0*/ break;
     180                case ThicknessAbsGradientEnum:    /*Nothing, \partial J/\partial k = 0*/ break;
     181                case ThicknessAlongGradientEnum:  /*Nothing, \partial J/\partial k = 0*/ break;
     182                case ThicknessAcrossGradientEnum: /*Nothing, \partial J/\partial k = 0*/ break;
     183                default: _error_("response " << EnumToStringx(responses[resp]) << " not supported yet");
     184        }
     185
     186        /*Deal with second term*/
     187        switch(control_type){
     188                case BalancethicknessThickeningRateEnum: GradientJDhDt(element,gradient,control_index); break;
     189                case VxEnum:                             GradientJVx(  element,gradient,control_index); break;
     190                case VyEnum:                             GradientJVy(  element,gradient,control_index); break;
     191                default: _error_("control type not supported yet: " << EnumToStringx(control_type));
     192        }
     193
     194        /*Clean up and return*/
     195        xDelete<int>(responses);
     196
     197}/*}}}*/
     198void AdjointBalancethicknessAnalysis::GradientJVx(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
     199
     200        /*Intermediaries*/
     201        IssmDouble Jdet,weight;
     202        IssmDouble thickness,Dlambda[3],dp[3];
     203        IssmDouble *xyz_list= NULL;
     204
     205        /*Fetch number of vertices for this finite element*/
     206        int numvertices = element->GetNumberOfVertices();
     207
     208        /*Initialize some vectors*/
     209        IssmDouble* basis         = xNew<IssmDouble>(numvertices);
     210        IssmDouble* ge            = xNewZeroInit<IssmDouble>(numvertices);
     211        int*        vertexpidlist = xNew<int>(numvertices);
     212
     213        /*Retrieve all inputs we will be needing: */
     214        element->GetVerticesCoordinates(&xyz_list);
     215        element->GradientIndexing(&vertexpidlist[0],control_index);
     216        Input* thickness_input = element->GetInput(ThicknessEnum); _assert_(thickness_input);
     217        Input* adjoint_input   = element->GetInput(AdjointEnum);   _assert_(adjoint_input);
     218
     219        /* Start  looping on the number of gaussian points: */
     220        Gauss* gauss=element->NewGauss(4);
     221        for(int ig=gauss->begin();ig<gauss->end();ig++){
     222                gauss->GaussPoint(ig);
     223
     224                adjoint_input->GetInputDerivativeValue(&Dlambda[0],xyz_list,gauss);
     225                thickness_input->GetInputValue(&thickness, gauss);
     226                thickness_input->GetInputDerivativeValue(&dp[0],xyz_list,gauss);
     227
     228                element->JacobianDeterminant(&Jdet,xyz_list,gauss);
     229                element->NodalFunctionsP1(basis,gauss);
     230
     231                /*Build gradient vector (actually -dJ/dD): */
     232                for(int i=0;i<numvertices;i++){
     233                        ge[i]+=thickness*Dlambda[0]*Jdet*gauss->weight*basis[i];
     234                        _assert_(!xIsNan<IssmDouble>(ge[i]));
     235                }
     236        }
     237        gradient->SetValues(numvertices,vertexpidlist,ge,ADD_VAL);
     238
     239        /*Clean up and return*/
     240        xDelete<IssmDouble>(xyz_list);
     241        xDelete<IssmDouble>(basis);
     242        xDelete<IssmDouble>(ge);
     243        xDelete<int>(vertexpidlist);
     244        delete gauss;
     245}/*}}}*/
     246void AdjointBalancethicknessAnalysis::GradientJVy(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
     247
     248        /*Intermediaries*/
     249        IssmDouble Jdet,weight;
     250        IssmDouble thickness,Dlambda[3],dp[3];
     251        IssmDouble *xyz_list= NULL;
     252
     253        /*Fetch number of vertices for this finite element*/
     254        int numvertices = element->GetNumberOfVertices();
     255
     256        /*Initialize some vectors*/
     257        IssmDouble* basis         = xNew<IssmDouble>(numvertices);
     258        IssmDouble* ge            = xNewZeroInit<IssmDouble>(numvertices);
     259        int*        vertexpidlist = xNew<int>(numvertices);
     260
     261        /*Retrieve all inputs we will be needing: */
     262        element->GetVerticesCoordinates(&xyz_list);
     263        element->GradientIndexing(&vertexpidlist[0],control_index);
     264        Input* thickness_input = element->GetInput(ThicknessEnum); _assert_(thickness_input);
     265        Input* adjoint_input   = element->GetInput(AdjointEnum);   _assert_(adjoint_input);
     266
     267        /* Start  looping on the number of gaussian points: */
     268        Gauss* gauss=element->NewGauss(4);
     269        for(int ig=gauss->begin();ig<gauss->end();ig++){
     270                gauss->GaussPoint(ig);
     271
     272                adjoint_input->GetInputDerivativeValue(&Dlambda[0],xyz_list,gauss);
     273                thickness_input->GetInputValue(&thickness, gauss);
     274                thickness_input->GetInputDerivativeValue(&dp[0],xyz_list,gauss);
     275
     276                element->JacobianDeterminant(&Jdet,xyz_list,gauss);
     277                element->NodalFunctionsP1(basis,gauss);
     278
     279                /*Build gradient vector (actually -dJ/dvy): */
     280                for(int i=0;i<numvertices;i++){
     281                        ge[i]+=thickness*Dlambda[1]*Jdet*gauss->weight*basis[i];
     282                        _assert_(!xIsNan<IssmDouble>(ge[i]));
     283                }
     284        }
     285        gradient->SetValues(numvertices,vertexpidlist,ge,ADD_VAL);
     286
     287        /*Clean up and return*/
     288        xDelete<IssmDouble>(xyz_list);
     289        xDelete<IssmDouble>(basis);
     290        xDelete<IssmDouble>(ge);
     291        xDelete<int>(vertexpidlist);
     292        delete gauss;
     293}/*}}}*/
     294void AdjointBalancethicknessAnalysis::GradientJDhDt(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
     295
     296        /*Fetch number of vertices for this finite element*/
     297        int numvertices = element->GetNumberOfVertices();
     298
     299        /*Initialize some vectors*/
     300        IssmDouble* ge            = xNewZeroInit<IssmDouble>(numvertices);
     301        IssmDouble* lambda        = xNew<IssmDouble>(numvertices);
     302        int*        vertexpidlist = xNew<int>(numvertices);
     303
     304        /*Retrieve all inputs we will be needing: */
     305        element->GradientIndexing(&vertexpidlist[0],control_index);
     306        element->GetInputListOnVertices(lambda,AdjointEnum);
     307        for(int i=0;i<numvertices;i++){
     308                ge[i]=-lambda[i];
     309                _assert_(!xIsNan<IssmDouble>(ge[i]));
     310        }
     311        gradient->SetValues(numvertices,vertexpidlist,ge,INS_VAL);
     312
     313        /*Clean up and return*/
     314        xDelete<IssmDouble>(ge);
     315        xDelete<IssmDouble>(lambda);
     316        xDelete<int>(vertexpidlist);
    154317}/*}}}*/
    155318void AdjointBalancethicknessAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
Note: See TracChangeset for help on using the changeset viewer.