Changeset 18930


Ignore:
Timestamp:
12/04/14 10:34:36 (10 years ago)
Author:
seroussi
Message:

CHG: minor ordering

Location:
issm/trunk-jpl/src/c/analyses
Files:
44 edited

Legend:

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

    r18715 r18930  
    66
    77/*Model processor*/
     8void AdjointBalancethickness2Analysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
     9        _error_("not implemented yet");
     10}/*}}}*/
     11void AdjointBalancethickness2Analysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
     12        _error_("not implemented yet");
     13}/*}}}*/
     14void AdjointBalancethickness2Analysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
     15        _error_("not implemented yet");
     16}/*}}}*/
    817int  AdjointBalancethickness2Analysis::DofsPerNode(int** doflist,int domaintype,int approximation){/*{{{*/
    918        return 1;
    1019}/*}}}*/
     20void AdjointBalancethickness2Analysis::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/
     21        _error_("not implemented yet");
     22}/*}}}*/
    1123void AdjointBalancethickness2Analysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
    12         _error_("not implemented yet");
    13 }/*}}}*/
    14 void AdjointBalancethickness2Analysis::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/
    15         _error_("not implemented yet");
    16 }/*}}}*/
    17 void AdjointBalancethickness2Analysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
    18         _error_("not implemented yet");
    19 }/*}}}*/
    20 void AdjointBalancethickness2Analysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
    21         _error_("not implemented yet");
    22 }/*}}}*/
    23 void AdjointBalancethickness2Analysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
    2424        _error_("not implemented yet");
    2525}/*}}}*/
     
    106106
    107107}/*}}}*/
    108 void AdjointBalancethickness2Analysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
    109         _error_("not implemented yet");
    110 }/*}}}*/
    111 void AdjointBalancethickness2Analysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
     108void           AdjointBalancethickness2Analysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
     109        _error_("not implemented yet");
     110}/*}}}*/
     111void           AdjointBalancethickness2Analysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
    112112        /*The gradient of the cost function is calculated in 2 parts.
    113113         *
     
    146146
    147147}/*}}}*/
    148 void AdjointBalancethickness2Analysis::GradientJOmega(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
     148void           AdjointBalancethickness2Analysis::GradientJdHdt(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
     149
     150        /*Intermediaries*/
     151        IssmDouble lambda,Jdet;
     152        IssmDouble *xyz_list= NULL;
     153
     154        /*Fetch number of vertices for this finite element*/
     155        int numvertices = element->GetNumberOfVertices();
     156
     157        /*Initialize some vectors*/
     158        IssmDouble* basis         = xNew<IssmDouble>(numvertices);
     159        IssmDouble* ge            = xNewZeroInit<IssmDouble>(numvertices);
     160        int*        vertexpidlist = xNew<int>(numvertices);
     161
     162        /*Retrieve all inputs we will be needing: */
     163        element->GetVerticesCoordinates(&xyz_list);
     164        element->GradientIndexing(&vertexpidlist[0],control_index);
     165        Input* adjoint_input = element->GetInput(AdjointEnum);            _assert_(adjoint_input);
     166
     167        Gauss* gauss=element->NewGauss(2);
     168        for(int ig=gauss->begin();ig<gauss->end();ig++){
     169                gauss->GaussPoint(ig);
     170
     171                element->JacobianDeterminant(&Jdet,xyz_list,gauss);
     172                element->NodalFunctionsP1(basis,gauss);
     173
     174                adjoint_input->GetInputValue(&lambda,gauss);
     175
     176                /*Build gradient vector (actually -dJ/da): */
     177                for(int i=0;i<numvertices;i++){
     178                        ge[i]+= -Jdet*gauss->weight*basis[i]*lambda;
     179                        _assert_(!xIsNan<IssmDouble>(ge[i]));
     180                }
     181        }
     182        gradient->SetValues(numvertices,vertexpidlist,ge,ADD_VAL);
     183
     184        /*Clean up and return*/
     185        xDelete<IssmDouble>(ge);
     186        xDelete<IssmDouble>(xyz_list);
     187        xDelete<IssmDouble>(basis);
     188        xDelete<int>(vertexpidlist);
     189        delete gauss;
     190}/*}}}*/
     191void           AdjointBalancethickness2Analysis::GradientJOmega(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
    149192
    150193        /*Intermediaries*/
     
    195238        delete gauss;
    196239}/*}}}*/
    197 void AdjointBalancethickness2Analysis::GradientJdHdt(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
    198 
    199         /*Intermediaries*/
    200         IssmDouble lambda,Jdet;
    201         IssmDouble *xyz_list= NULL;
    202 
    203         /*Fetch number of vertices for this finite element*/
    204         int numvertices = element->GetNumberOfVertices();
    205 
    206         /*Initialize some vectors*/
    207         IssmDouble* basis         = xNew<IssmDouble>(numvertices);
    208         IssmDouble* ge            = xNewZeroInit<IssmDouble>(numvertices);
    209         int*        vertexpidlist = xNew<int>(numvertices);
    210 
    211         /*Retrieve all inputs we will be needing: */
    212         element->GetVerticesCoordinates(&xyz_list);
    213         element->GradientIndexing(&vertexpidlist[0],control_index);
    214         Input* adjoint_input = element->GetInput(AdjointEnum);            _assert_(adjoint_input);
    215 
    216         Gauss* gauss=element->NewGauss(2);
    217         for(int ig=gauss->begin();ig<gauss->end();ig++){
    218                 gauss->GaussPoint(ig);
    219 
    220                 element->JacobianDeterminant(&Jdet,xyz_list,gauss);
    221                 element->NodalFunctionsP1(basis,gauss);
    222 
    223                 adjoint_input->GetInputValue(&lambda,gauss);
    224 
    225                 /*Build gradient vector (actually -dJ/da): */
    226                 for(int i=0;i<numvertices;i++){
    227                         ge[i]+= -Jdet*gauss->weight*basis[i]*lambda;
    228                         _assert_(!xIsNan<IssmDouble>(ge[i]));
    229                 }
    230         }
    231         gradient->SetValues(numvertices,vertexpidlist,ge,ADD_VAL);
    232 
    233         /*Clean up and return*/
    234         xDelete<IssmDouble>(ge);
    235         xDelete<IssmDouble>(xyz_list);
    236         xDelete<IssmDouble>(basis);
    237         xDelete<int>(vertexpidlist);
    238         delete gauss;
    239 }/*}}}*/
    240 void AdjointBalancethickness2Analysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
     240void           AdjointBalancethickness2Analysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
    241241        element->InputUpdateFromSolutionOneDof(solution,AdjointEnum);
    242242}/*}}}*/
    243 void AdjointBalancethickness2Analysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
     243void           AdjointBalancethickness2Analysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
    244244        /*Default, do nothing*/
    245245        return;
  • issm/trunk-jpl/src/c/analyses/AdjointBalancethickness2Analysis.h

    r18569 r18930  
    1313        public:
    1414                /*Model processing*/
    15                 int  DofsPerNode(int** doflist,int domaintype,int approximation);
    16                 void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);
    17                 void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);
    18                 void CreateNodes(Nodes* nodes,IoModel* iomodel);
    1915                void CreateConstraints(Constraints* constraints,IoModel* iomodel);
    2016                void CreateLoads(Loads* loads, IoModel* iomodel);
     17                void CreateNodes(Nodes* nodes,IoModel* iomodel);
     18                int  DofsPerNode(int** doflist,int domaintype,int approximation);
     19                void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);
     20                void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);
    2121
    2222                /*Finite element Analysis*/
     
    2626                ElementMatrix* CreateKMatrix(Element* element);
    2727                ElementVector* CreatePVector(Element* element);
    28                 void GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);
    29                 void GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);
    30                 void GradientJOmega(Element* element,Vector<IssmDouble>* gradient,int control_index);
    31                 void GradientJdHdt(Element* element,Vector<IssmDouble>* gradient,int control_index);
    32                 void InputUpdateFromSolution(IssmDouble* solution,Element* element);
    33                 void UpdateConstraints(FemModel* femmodel);
     28                void           GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);
     29                void           GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);
     30                void           GradientJdHdt(Element* element,Vector<IssmDouble>* gradient,int control_index);
     31                void           GradientJOmega(Element* element,Vector<IssmDouble>* gradient,int control_index);
     32                void           InputUpdateFromSolution(IssmDouble* solution,Element* element);
     33                void           UpdateConstraints(FemModel* femmodel);
    3434};
    3535#endif
  • issm/trunk-jpl/src/c/analyses/AdjointBalancethicknessAnalysis.cpp

    r18403 r18930  
    66
    77/*Model processor*/
     8void AdjointBalancethicknessAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
     9        _error_("not implemented yet");
     10}/*}}}*/
     11void AdjointBalancethicknessAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
     12        _error_("not implemented yet");
     13}/*}}}*/
     14void AdjointBalancethicknessAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
     15        _error_("not implemented yet");
     16}/*}}}*/
    817int  AdjointBalancethicknessAnalysis::DofsPerNode(int** doflist,int domaintype,int approximation){/*{{{*/
    918        return 1;
    1019}/*}}}*/
     20void AdjointBalancethicknessAnalysis::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/
     21        _error_("not implemented yet");
     22}/*}}}*/
    1123void AdjointBalancethicknessAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
    12         _error_("not implemented yet");
    13 }/*}}}*/
    14 void AdjointBalancethicknessAnalysis::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/
    15         _error_("not implemented yet");
    16 }/*}}}*/
    17 void AdjointBalancethicknessAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
    18         _error_("not implemented yet");
    19 }/*}}}*/
    20 void AdjointBalancethicknessAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
    21         _error_("not implemented yet");
    22 }/*}}}*/
    23 void AdjointBalancethicknessAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
    2424        _error_("not implemented yet");
    2525}/*}}}*/
     
    147147        return pe;
    148148}/*}}}*/
    149 void AdjointBalancethicknessAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
    150         _error_("not implemented yet");
    151 }/*}}}*/
    152 void AdjointBalancethicknessAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
     149void           AdjointBalancethicknessAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
     150        _error_("not implemented yet");
     151}/*}}}*/
     152void           AdjointBalancethicknessAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
    153153        /*The gradient of the cost function is calculated in 2 parts.
    154154         *
     
    196196
    197197}/*}}}*/
    198 void AdjointBalancethicknessAnalysis::GradientJVx(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
    199 
    200         /*Intermediaries*/
    201         IssmDouble thickness,Jdet,Dlambda[3],dp[3];
    202         IssmDouble *xyz_list= NULL;
    203 
    204         /*Fetch number of vertices for this finite element*/
    205         int numvertices = element->GetNumberOfVertices();
    206 
    207         /*Initialize some vectors*/
    208         IssmDouble* basis         = xNew<IssmDouble>(numvertices);
    209         IssmDouble* ge            = xNewZeroInit<IssmDouble>(numvertices);
    210         int*        vertexpidlist = xNew<int>(numvertices);
    211 
    212         /*Retrieve all inputs we will be needing: */
    213         element->GetVerticesCoordinates(&xyz_list);
    214         element->GradientIndexing(&vertexpidlist[0],control_index);
    215         Input* thickness_input = element->GetInput(ThicknessEnum); _assert_(thickness_input);
    216         Input* adjoint_input   = element->GetInput(AdjointEnum);   _assert_(adjoint_input);
    217 
    218         /* Start  looping on the number of gaussian points: */
    219         Gauss* gauss=element->NewGauss(4);
    220         for(int ig=gauss->begin();ig<gauss->end();ig++){
    221                 gauss->GaussPoint(ig);
    222 
    223                 adjoint_input->GetInputDerivativeValue(&Dlambda[0],xyz_list,gauss);
    224                 thickness_input->GetInputValue(&thickness, gauss);
    225                 thickness_input->GetInputDerivativeValue(&dp[0],xyz_list,gauss);
    226 
    227                 element->JacobianDeterminant(&Jdet,xyz_list,gauss);
    228                 element->NodalFunctionsP1(basis,gauss);
    229 
    230                 /*Build gradient vector (actually -dJ/dD): */
    231                 for(int i=0;i<numvertices;i++){
    232                         ge[i]+=thickness*Dlambda[0]*Jdet*gauss->weight*basis[i];
    233                         _assert_(!xIsNan<IssmDouble>(ge[i]));
    234                 }
    235         }
    236         gradient->SetValues(numvertices,vertexpidlist,ge,ADD_VAL);
    237 
    238         /*Clean up and return*/
    239         xDelete<IssmDouble>(xyz_list);
    240         xDelete<IssmDouble>(basis);
    241         xDelete<IssmDouble>(ge);
    242         xDelete<int>(vertexpidlist);
    243         delete gauss;
    244 }/*}}}*/
    245 void AdjointBalancethicknessAnalysis::GradientJVy(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
    246 
    247         /*Intermediaries*/
    248         IssmDouble thickness,Jdet,Dlambda[3],dp[3];
    249         IssmDouble *xyz_list= NULL;
    250 
    251         /*Fetch number of vertices for this finite element*/
    252         int numvertices = element->GetNumberOfVertices();
    253 
    254         /*Initialize some vectors*/
    255         IssmDouble* basis         = xNew<IssmDouble>(numvertices);
    256         IssmDouble* ge            = xNewZeroInit<IssmDouble>(numvertices);
    257         int*        vertexpidlist = xNew<int>(numvertices);
    258 
    259         /*Retrieve all inputs we will be needing: */
    260         element->GetVerticesCoordinates(&xyz_list);
    261         element->GradientIndexing(&vertexpidlist[0],control_index);
    262         Input* thickness_input = element->GetInput(ThicknessEnum); _assert_(thickness_input);
    263         Input* adjoint_input   = element->GetInput(AdjointEnum);   _assert_(adjoint_input);
    264 
    265         /* Start  looping on the number of gaussian points: */
    266         Gauss* gauss=element->NewGauss(4);
    267         for(int ig=gauss->begin();ig<gauss->end();ig++){
    268                 gauss->GaussPoint(ig);
    269 
    270                 adjoint_input->GetInputDerivativeValue(&Dlambda[0],xyz_list,gauss);
    271                 thickness_input->GetInputValue(&thickness, gauss);
    272                 thickness_input->GetInputDerivativeValue(&dp[0],xyz_list,gauss);
    273 
    274                 element->JacobianDeterminant(&Jdet,xyz_list,gauss);
    275                 element->NodalFunctionsP1(basis,gauss);
    276 
    277                 /*Build gradient vector (actually -dJ/dvy): */
    278                 for(int i=0;i<numvertices;i++){
    279                         ge[i]+=thickness*Dlambda[1]*Jdet*gauss->weight*basis[i];
    280                         _assert_(!xIsNan<IssmDouble>(ge[i]));
    281                 }
    282         }
    283         gradient->SetValues(numvertices,vertexpidlist,ge,ADD_VAL);
    284 
    285         /*Clean up and return*/
    286         xDelete<IssmDouble>(xyz_list);
    287         xDelete<IssmDouble>(basis);
    288         xDelete<IssmDouble>(ge);
    289         xDelete<int>(vertexpidlist);
    290         delete gauss;
    291 }/*}}}*/
    292 void AdjointBalancethicknessAnalysis::GradientJDhDt(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
     198void           AdjointBalancethicknessAnalysis::GradientJDhDt(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
    293199
    294200        /*Fetch number of vertices for this finite element*/
     
    314220        xDelete<int>(vertexpidlist);
    315221}/*}}}*/
    316 void AdjointBalancethicknessAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
     222void           AdjointBalancethicknessAnalysis::GradientJVx(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
     223
     224        /*Intermediaries*/
     225        IssmDouble thickness,Jdet,Dlambda[3],dp[3];
     226        IssmDouble *xyz_list= NULL;
     227
     228        /*Fetch number of vertices for this finite element*/
     229        int numvertices = element->GetNumberOfVertices();
     230
     231        /*Initialize some vectors*/
     232        IssmDouble* basis         = xNew<IssmDouble>(numvertices);
     233        IssmDouble* ge            = xNewZeroInit<IssmDouble>(numvertices);
     234        int*        vertexpidlist = xNew<int>(numvertices);
     235
     236        /*Retrieve all inputs we will be needing: */
     237        element->GetVerticesCoordinates(&xyz_list);
     238        element->GradientIndexing(&vertexpidlist[0],control_index);
     239        Input* thickness_input = element->GetInput(ThicknessEnum); _assert_(thickness_input);
     240        Input* adjoint_input   = element->GetInput(AdjointEnum);   _assert_(adjoint_input);
     241
     242        /* Start  looping on the number of gaussian points: */
     243        Gauss* gauss=element->NewGauss(4);
     244        for(int ig=gauss->begin();ig<gauss->end();ig++){
     245                gauss->GaussPoint(ig);
     246
     247                adjoint_input->GetInputDerivativeValue(&Dlambda[0],xyz_list,gauss);
     248                thickness_input->GetInputValue(&thickness, gauss);
     249                thickness_input->GetInputDerivativeValue(&dp[0],xyz_list,gauss);
     250
     251                element->JacobianDeterminant(&Jdet,xyz_list,gauss);
     252                element->NodalFunctionsP1(basis,gauss);
     253
     254                /*Build gradient vector (actually -dJ/dD): */
     255                for(int i=0;i<numvertices;i++){
     256                        ge[i]+=thickness*Dlambda[0]*Jdet*gauss->weight*basis[i];
     257                        _assert_(!xIsNan<IssmDouble>(ge[i]));
     258                }
     259        }
     260        gradient->SetValues(numvertices,vertexpidlist,ge,ADD_VAL);
     261
     262        /*Clean up and return*/
     263        xDelete<IssmDouble>(xyz_list);
     264        xDelete<IssmDouble>(basis);
     265        xDelete<IssmDouble>(ge);
     266        xDelete<int>(vertexpidlist);
     267        delete gauss;
     268}/*}}}*/
     269void           AdjointBalancethicknessAnalysis::GradientJVy(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
     270
     271        /*Intermediaries*/
     272        IssmDouble thickness,Jdet,Dlambda[3],dp[3];
     273        IssmDouble *xyz_list= NULL;
     274
     275        /*Fetch number of vertices for this finite element*/
     276        int numvertices = element->GetNumberOfVertices();
     277
     278        /*Initialize some vectors*/
     279        IssmDouble* basis         = xNew<IssmDouble>(numvertices);
     280        IssmDouble* ge            = xNewZeroInit<IssmDouble>(numvertices);
     281        int*        vertexpidlist = xNew<int>(numvertices);
     282
     283        /*Retrieve all inputs we will be needing: */
     284        element->GetVerticesCoordinates(&xyz_list);
     285        element->GradientIndexing(&vertexpidlist[0],control_index);
     286        Input* thickness_input = element->GetInput(ThicknessEnum); _assert_(thickness_input);
     287        Input* adjoint_input   = element->GetInput(AdjointEnum);   _assert_(adjoint_input);
     288
     289        /* Start  looping on the number of gaussian points: */
     290        Gauss* gauss=element->NewGauss(4);
     291        for(int ig=gauss->begin();ig<gauss->end();ig++){
     292                gauss->GaussPoint(ig);
     293
     294                adjoint_input->GetInputDerivativeValue(&Dlambda[0],xyz_list,gauss);
     295                thickness_input->GetInputValue(&thickness, gauss);
     296                thickness_input->GetInputDerivativeValue(&dp[0],xyz_list,gauss);
     297
     298                element->JacobianDeterminant(&Jdet,xyz_list,gauss);
     299                element->NodalFunctionsP1(basis,gauss);
     300
     301                /*Build gradient vector (actually -dJ/dvy): */
     302                for(int i=0;i<numvertices;i++){
     303                        ge[i]+=thickness*Dlambda[1]*Jdet*gauss->weight*basis[i];
     304                        _assert_(!xIsNan<IssmDouble>(ge[i]));
     305                }
     306        }
     307        gradient->SetValues(numvertices,vertexpidlist,ge,ADD_VAL);
     308
     309        /*Clean up and return*/
     310        xDelete<IssmDouble>(xyz_list);
     311        xDelete<IssmDouble>(basis);
     312        xDelete<IssmDouble>(ge);
     313        xDelete<int>(vertexpidlist);
     314        delete gauss;
     315}/*}}}*/
     316void           AdjointBalancethicknessAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
    317317
    318318        int domaintype;
     
    328328        }
    329329}/*}}}*/
    330 void AdjointBalancethicknessAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
     330void           AdjointBalancethicknessAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
    331331        /*Default, do nothing*/
    332332        return;
  • issm/trunk-jpl/src/c/analyses/AdjointBalancethicknessAnalysis.h

    r18060 r18930  
    1313        public:
    1414                /*Model processing*/
    15                 int  DofsPerNode(int** doflist,int domaintype,int approximation);
    16                 void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);
    17                 void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);
    18                 void CreateNodes(Nodes* nodes,IoModel* iomodel);
    1915                void CreateConstraints(Constraints* constraints,IoModel* iomodel);
    2016                void CreateLoads(Loads* loads, IoModel* iomodel);
     17                void CreateNodes(Nodes* nodes,IoModel* iomodel);
     18                int  DofsPerNode(int** doflist,int domaintype,int approximation);
     19                void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);
     20                void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);
    2121
    2222                /*Finite element Analysis*/
     
    2626                ElementMatrix* CreateKMatrix(Element* element);
    2727                ElementVector* CreatePVector(Element* element);
    28                 void GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);
    29                 void GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);
    30                 void GradientJVx(Element* element,Vector<IssmDouble>* gradient,int control_index);
    31                 void GradientJVy(Element* element,Vector<IssmDouble>* gradient,int control_index);
    32                 void GradientJDhDt(Element* element,Vector<IssmDouble>* gradient,int control_index);
    33                 void InputUpdateFromSolution(IssmDouble* solution,Element* element);
    34                 void UpdateConstraints(FemModel* femmodel);
     28                void           GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);
     29                void           GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);
     30                void           GradientJDhDt(Element* element,Vector<IssmDouble>* gradient,int control_index);
     31                void           GradientJVx(Element* element,Vector<IssmDouble>* gradient,int control_index);
     32                void           GradientJVy(Element* element,Vector<IssmDouble>* gradient,int control_index);
     33                void           InputUpdateFromSolution(IssmDouble* solution,Element* element);
     34                void           UpdateConstraints(FemModel* femmodel);
    3535};
    3636#endif
  • issm/trunk-jpl/src/c/analyses/AdjointHorizAnalysis.cpp

    r18838 r18930  
    66
    77/*Model processing*/
     8void AdjointHorizAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
     9           _error_("not implemented yet");
     10}/*}}}*/
     11void AdjointHorizAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
     12           _error_("not implemented yet");
     13}/*}}}*/
     14void AdjointHorizAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
     15           _error_("not implemented yet");
     16}/*}}}*/
    817int  AdjointHorizAnalysis::DofsPerNode(int** doflist,int domaintype,int approximation){/*{{{*/
    918        _error_("not implemented");
    1019}/*}}}*/
    11 void AdjointHorizAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
    12            _error_("not implemented yet");
    13 }/*}}}*/
    1420void AdjointHorizAnalysis::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/
    1521           _error_("not implemented yet");
    1622}/*}}}*/
    17 void AdjointHorizAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
    18            _error_("not implemented yet");
    19 }/*}}}*/
    20 void AdjointHorizAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
    21            _error_("not implemented yet");
    22 }/*}}}*/
    23 void AdjointHorizAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
     23void AdjointHorizAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
    2424           _error_("not implemented yet");
    2525}/*}}}*/
     
    5454        }
    5555}/*}}}*/
     56ElementMatrix* AdjointHorizAnalysis::CreateKMatrixFS(Element* element){/*{{{*/
     57
     58        /*Intermediaries */
     59        bool        incomplete_adjoint;
     60        int         dim,epssize;
     61        IssmDouble  Jdet,mu_prime;
     62        IssmDouble  eps1dotdphii,eps1dotdphij,eps2dotdphii,eps2dotdphij,eps3dotdphii,eps3dotdphij;
     63        IssmDouble  eps1[3],eps2[3],eps3[3],epsilon[5];/* epsilon=[exx,eyy,exy,exz,eyz];*/
     64        IssmDouble *xyz_list = NULL;
     65
     66        /*Get problem dimension*/
     67        element->FindParam(&dim,DomainDimensionEnum);
     68        if(dim==2) epssize = 3;
     69        else       epssize = 6;
     70
     71        /*Fetch number of nodes and dof for this finite element*/
     72        int vnumnodes = element->NumberofNodesVelocity();
     73        int pnumnodes = element->NumberofNodesPressure();
     74        int numdof    = vnumnodes*dim + pnumnodes;
     75
     76        /*Initialize Jacobian with regular FS (first part of the Gateau derivative)*/
     77        element->FindParam(&incomplete_adjoint,InversionIncompleteAdjointEnum);
     78        StressbalanceAnalysis* analysis = new StressbalanceAnalysis();
     79        ElementMatrix* Ke=analysis->CreateKMatrix(element);
     80        delete analysis;
     81        if(incomplete_adjoint) return Ke;
     82
     83        /*Retrieve all inputs and parameters*/
     84        element->GetVerticesCoordinates(&xyz_list);
     85        Input* vx_input = element->GetInput(VxEnum);_assert_(vx_input);
     86        Input* vy_input = element->GetInput(VyEnum);_assert_(vy_input);
     87        Input* vz_input = NULL;
     88        if(dim==3){
     89                vz_input = element->GetInput(VzEnum);
     90        }
     91        else{
     92                _error_("Not implemented yet");
     93        }
     94
     95        /*Allocate dbasis*/
     96        IssmDouble* dbasis = xNew<IssmDouble>(dim*vnumnodes);
     97
     98        /* Start  looping on the number of gaussian points: */
     99        Gauss* gauss=element->NewGauss(5);
     100        for(int ig=gauss->begin();ig<gauss->end();ig++){
     101                gauss->GaussPoint(ig);
     102
     103                element->JacobianDeterminant(&Jdet,xyz_list,gauss);
     104                element->NodalFunctionsDerivatives(dbasis,xyz_list,gauss);
     105
     106                element->StrainRateHO(&epsilon[0],xyz_list,gauss,vx_input,vy_input);
     107                element->ViscosityFSDerivativeEpsSquare(&mu_prime,&epsilon[0]);
     108                eps1[0]=epsilon[0];   eps2[0]=epsilon[2];   eps3[0]=epsilon[3];
     109                eps1[1]=epsilon[2];   eps2[1]=epsilon[1];   eps3[1]=epsilon[4];
     110                eps1[2]=epsilon[3];   eps2[2]=epsilon[4];   eps3[2]= -epsilon[0] -epsilon[1];
     111
     112                for(int i=0;i<vnumnodes;i++){
     113                        for(int j=0;j<vnumnodes;j++){
     114                                eps1dotdphii=eps1[0]*dbasis[0*vnumnodes+i]+eps1[1]*dbasis[1*vnumnodes+i]+eps1[2]*dbasis[2*vnumnodes+i];
     115                                eps1dotdphij=eps1[0]*dbasis[0*vnumnodes+j]+eps1[1]*dbasis[1*vnumnodes+j]+eps1[2]*dbasis[2*vnumnodes+j];
     116                                eps2dotdphii=eps2[0]*dbasis[0*vnumnodes+i]+eps2[1]*dbasis[1*vnumnodes+i]+eps2[2]*dbasis[2*vnumnodes+i];
     117                                eps2dotdphij=eps2[0]*dbasis[0*vnumnodes+j]+eps2[1]*dbasis[1*vnumnodes+j]+eps2[2]*dbasis[2*vnumnodes+j];
     118                                eps3dotdphii=eps3[0]*dbasis[0*vnumnodes+i]+eps3[1]*dbasis[1*vnumnodes+i]+eps3[2]*dbasis[2*vnumnodes+i];
     119                                eps3dotdphij=eps3[0]*dbasis[0*vnumnodes+j]+eps3[1]*dbasis[1*vnumnodes+j]+eps3[2]*dbasis[2*vnumnodes+j];
     120
     121                                Ke->values[numdof*(4*i+0)+4*j+0]+=gauss->weight*Jdet*2*mu_prime*eps1dotdphij*eps1dotdphii;
     122                                Ke->values[numdof*(4*i+0)+4*j+1]+=gauss->weight*Jdet*2*mu_prime*eps2dotdphij*eps1dotdphii;
     123                                Ke->values[numdof*(4*i+0)+4*j+2]+=gauss->weight*Jdet*2*mu_prime*eps3dotdphij*eps1dotdphii;
     124
     125                                Ke->values[numdof*(4*i+1)+4*j+0]+=gauss->weight*Jdet*2*mu_prime*eps1dotdphij*eps2dotdphii;
     126                                Ke->values[numdof*(4*i+1)+4*j+1]+=gauss->weight*Jdet*2*mu_prime*eps2dotdphij*eps2dotdphii;
     127                                Ke->values[numdof*(4*i+1)+4*j+2]+=gauss->weight*Jdet*2*mu_prime*eps3dotdphij*eps2dotdphii;
     128
     129                                Ke->values[numdof*(4*i+2)+4*j+0]+=gauss->weight*Jdet*2*mu_prime*eps1dotdphij*eps3dotdphii;
     130                                Ke->values[numdof*(4*i+2)+4*j+1]+=gauss->weight*Jdet*2*mu_prime*eps2dotdphij*eps3dotdphii;
     131                                Ke->values[numdof*(4*i+2)+4*j+2]+=gauss->weight*Jdet*2*mu_prime*eps3dotdphij*eps3dotdphii;
     132                        }
     133                }
     134        }
     135
     136        /*Transform Coordinate System*/
     137        element->TransformStiffnessMatrixCoord(Ke,XYZEnum);
     138
     139        /*Clean up and return*/
     140        delete gauss;
     141        xDelete<IssmDouble>(dbasis);
     142        xDelete<IssmDouble>(xyz_list);
     143        return Ke;
     144}/*}}}*/
     145ElementMatrix* AdjointHorizAnalysis::CreateKMatrixHO(Element* element){/*{{{*/
     146
     147        /*Intermediaries */
     148        bool        incomplete_adjoint;
     149        IssmDouble  Jdet,mu_prime;
     150        IssmDouble  eps1dotdphii,eps1dotdphij,eps2dotdphii,eps2dotdphij;
     151        IssmDouble  eps1[3],eps2[3],epsilon[5];/* epsilon=[exx,eyy,exy,exz,eyz];*/
     152        IssmDouble *xyz_list = NULL;
     153
     154        /*Fetch number of nodes and dof for this finite element*/
     155        int numnodes = element->GetNumberOfNodes();
     156
     157        /*Initialize Jacobian with regular HO (first part of the Gateau derivative)*/
     158        element->FindParam(&incomplete_adjoint,InversionIncompleteAdjointEnum);
     159        StressbalanceAnalysis* analysis = new StressbalanceAnalysis();
     160        ElementMatrix* Ke=analysis->CreateKMatrix(element);
     161        delete analysis;
     162        if(incomplete_adjoint) return Ke;
     163
     164        /*Retrieve all inputs and parameters*/
     165        element->GetVerticesCoordinates(&xyz_list);
     166        Input* vx_input = element->GetInput(VxEnum); _assert_(vx_input);
     167        Input* vy_input = element->GetInput(VyEnum); _assert_(vy_input);
     168
     169        /*Allocate dbasis*/
     170        IssmDouble* dbasis = xNew<IssmDouble>(3*numnodes);
     171
     172        /* Start  looping on the number of gaussian points: */
     173        Gauss* gauss=element->NewGauss(5);
     174        for(int ig=gauss->begin();ig<gauss->end();ig++){
     175                gauss->GaussPoint(ig);
     176
     177                element->JacobianDeterminant(&Jdet,xyz_list,gauss);
     178                element->NodalFunctionsDerivatives(dbasis,xyz_list,gauss);
     179
     180                element->StrainRateHO(&epsilon[0],xyz_list,gauss,vx_input,vy_input);
     181                element->ViscosityHODerivativeEpsSquare(&mu_prime,&epsilon[0]);
     182                eps1[0]=2.*epsilon[0]+epsilon[1];   eps2[0]=epsilon[2];
     183                eps1[1]=epsilon[2];                 eps2[1]=epsilon[0]+2.*epsilon[1];
     184                eps1[2]=epsilon[3];                 eps2[2]=epsilon[4];
     185
     186                for(int i=0;i<numnodes;i++){
     187                        for(int j=0;j<numnodes;j++){
     188                                eps1dotdphii=eps1[0]*dbasis[0*numnodes+i]+eps1[1]*dbasis[1*numnodes+i]+eps1[2]*dbasis[2*numnodes+i];
     189                                eps1dotdphij=eps1[0]*dbasis[0*numnodes+j]+eps1[1]*dbasis[1*numnodes+j]+eps1[2]*dbasis[2*numnodes+j];
     190                                eps2dotdphii=eps2[0]*dbasis[0*numnodes+i]+eps2[1]*dbasis[1*numnodes+i]+eps2[2]*dbasis[2*numnodes+i];
     191                                eps2dotdphij=eps2[0]*dbasis[0*numnodes+j]+eps2[1]*dbasis[1*numnodes+j]+eps2[2]*dbasis[2*numnodes+j];
     192
     193                                Ke->values[2*numnodes*(2*i+0)+2*j+0]+=gauss->weight*Jdet*2*mu_prime*eps1dotdphij*eps1dotdphii;
     194                                Ke->values[2*numnodes*(2*i+0)+2*j+1]+=gauss->weight*Jdet*2*mu_prime*eps2dotdphij*eps1dotdphii;
     195                                Ke->values[2*numnodes*(2*i+1)+2*j+0]+=gauss->weight*Jdet*2*mu_prime*eps1dotdphij*eps2dotdphii;
     196                                Ke->values[2*numnodes*(2*i+1)+2*j+1]+=gauss->weight*Jdet*2*mu_prime*eps2dotdphij*eps2dotdphii;
     197                        }
     198                }
     199        }
     200
     201        /*Transform Coordinate System*/
     202        element->TransformStiffnessMatrixCoord(Ke,XYEnum);
     203
     204        /*Clean up and return*/
     205        delete gauss;
     206        xDelete<IssmDouble>(dbasis);
     207        xDelete<IssmDouble>(xyz_list);
     208        return Ke;
     209}/*}}}*/
     210ElementMatrix* AdjointHorizAnalysis::CreateKMatrixL1L2(Element* element){/*{{{*/
     211
     212        /*Intermediaries*/
     213        bool incomplete_adjoint;
     214
     215        /*Initialize Jacobian with regular L1L2 (first part of the Gateau derivative)*/
     216        StressbalanceAnalysis* analysis = new StressbalanceAnalysis();
     217        ElementMatrix* Ke=analysis->CreateKMatrix(element);
     218        delete analysis;
     219
     220        /*return*/
     221        element->FindParam(&incomplete_adjoint,InversionIncompleteAdjointEnum);
     222        if(!incomplete_adjoint){
     223                _error_("Exact adjoint not supported yet for L1L2 model");
     224        }
     225        return Ke;
     226}/*}}}*/
    56227ElementMatrix* AdjointHorizAnalysis::CreateKMatrixSSA(Element* element){/*{{{*/
    57228
     
    139310        xDelete<IssmDouble>(xyz_list);
    140311        if(domaintype!=Domain2DhorizontalEnum){basalelement->DeleteMaterials(); delete basalelement;};
    141         return Ke;
    142 }/*}}}*/
    143 ElementMatrix* AdjointHorizAnalysis::CreateKMatrixL1L2(Element* element){/*{{{*/
    144 
    145         /*Intermediaries*/
    146         bool incomplete_adjoint;
    147 
    148         /*Initialize Jacobian with regular L1L2 (first part of the Gateau derivative)*/
    149         StressbalanceAnalysis* analysis = new StressbalanceAnalysis();
    150         ElementMatrix* Ke=analysis->CreateKMatrix(element);
    151         delete analysis;
    152 
    153         /*return*/
    154         element->FindParam(&incomplete_adjoint,InversionIncompleteAdjointEnum);
    155         if(!incomplete_adjoint){
    156                 _error_("Exact adjoint not supported yet for L1L2 model");
    157         }
    158         return Ke;
    159 }/*}}}*/
    160 ElementMatrix* AdjointHorizAnalysis::CreateKMatrixHO(Element* element){/*{{{*/
    161 
    162         /*Intermediaries */
    163         bool        incomplete_adjoint;
    164         IssmDouble  Jdet,mu_prime;
    165         IssmDouble  eps1dotdphii,eps1dotdphij,eps2dotdphii,eps2dotdphij;
    166         IssmDouble  eps1[3],eps2[3],epsilon[5];/* epsilon=[exx,eyy,exy,exz,eyz];*/
    167         IssmDouble *xyz_list = NULL;
    168 
    169         /*Fetch number of nodes and dof for this finite element*/
    170         int numnodes = element->GetNumberOfNodes();
    171 
    172         /*Initialize Jacobian with regular HO (first part of the Gateau derivative)*/
    173         element->FindParam(&incomplete_adjoint,InversionIncompleteAdjointEnum);
    174         StressbalanceAnalysis* analysis = new StressbalanceAnalysis();
    175         ElementMatrix* Ke=analysis->CreateKMatrix(element);
    176         delete analysis;
    177         if(incomplete_adjoint) return Ke;
    178 
    179         /*Retrieve all inputs and parameters*/
    180         element->GetVerticesCoordinates(&xyz_list);
    181         Input* vx_input = element->GetInput(VxEnum); _assert_(vx_input);
    182         Input* vy_input = element->GetInput(VyEnum); _assert_(vy_input);
    183 
    184         /*Allocate dbasis*/
    185         IssmDouble* dbasis = xNew<IssmDouble>(3*numnodes);
    186 
    187         /* Start  looping on the number of gaussian points: */
    188         Gauss* gauss=element->NewGauss(5);
    189         for(int ig=gauss->begin();ig<gauss->end();ig++){
    190                 gauss->GaussPoint(ig);
    191 
    192                 element->JacobianDeterminant(&Jdet,xyz_list,gauss);
    193                 element->NodalFunctionsDerivatives(dbasis,xyz_list,gauss);
    194 
    195                 element->StrainRateHO(&epsilon[0],xyz_list,gauss,vx_input,vy_input);
    196                 element->ViscosityHODerivativeEpsSquare(&mu_prime,&epsilon[0]);
    197                 eps1[0]=2.*epsilon[0]+epsilon[1];   eps2[0]=epsilon[2];
    198                 eps1[1]=epsilon[2];                 eps2[1]=epsilon[0]+2.*epsilon[1];
    199                 eps1[2]=epsilon[3];                 eps2[2]=epsilon[4];
    200 
    201                 for(int i=0;i<numnodes;i++){
    202                         for(int j=0;j<numnodes;j++){
    203                                 eps1dotdphii=eps1[0]*dbasis[0*numnodes+i]+eps1[1]*dbasis[1*numnodes+i]+eps1[2]*dbasis[2*numnodes+i];
    204                                 eps1dotdphij=eps1[0]*dbasis[0*numnodes+j]+eps1[1]*dbasis[1*numnodes+j]+eps1[2]*dbasis[2*numnodes+j];
    205                                 eps2dotdphii=eps2[0]*dbasis[0*numnodes+i]+eps2[1]*dbasis[1*numnodes+i]+eps2[2]*dbasis[2*numnodes+i];
    206                                 eps2dotdphij=eps2[0]*dbasis[0*numnodes+j]+eps2[1]*dbasis[1*numnodes+j]+eps2[2]*dbasis[2*numnodes+j];
    207 
    208                                 Ke->values[2*numnodes*(2*i+0)+2*j+0]+=gauss->weight*Jdet*2*mu_prime*eps1dotdphij*eps1dotdphii;
    209                                 Ke->values[2*numnodes*(2*i+0)+2*j+1]+=gauss->weight*Jdet*2*mu_prime*eps2dotdphij*eps1dotdphii;
    210                                 Ke->values[2*numnodes*(2*i+1)+2*j+0]+=gauss->weight*Jdet*2*mu_prime*eps1dotdphij*eps2dotdphii;
    211                                 Ke->values[2*numnodes*(2*i+1)+2*j+1]+=gauss->weight*Jdet*2*mu_prime*eps2dotdphij*eps2dotdphii;
    212                         }
    213                 }
    214         }
    215 
    216         /*Transform Coordinate System*/
    217         element->TransformStiffnessMatrixCoord(Ke,XYEnum);
    218 
    219         /*Clean up and return*/
    220         delete gauss;
    221         xDelete<IssmDouble>(dbasis);
    222         xDelete<IssmDouble>(xyz_list);
    223         return Ke;
    224 }/*}}}*/
    225 ElementMatrix* AdjointHorizAnalysis::CreateKMatrixFS(Element* element){/*{{{*/
    226 
    227         /*Intermediaries */
    228         bool        incomplete_adjoint;
    229         int         dim,epssize;
    230         IssmDouble  Jdet,mu_prime;
    231         IssmDouble  eps1dotdphii,eps1dotdphij,eps2dotdphii,eps2dotdphij,eps3dotdphii,eps3dotdphij;
    232         IssmDouble  eps1[3],eps2[3],eps3[3],epsilon[5];/* epsilon=[exx,eyy,exy,exz,eyz];*/
    233         IssmDouble *xyz_list = NULL;
    234 
    235         /*Get problem dimension*/
    236         element->FindParam(&dim,DomainDimensionEnum);
    237         if(dim==2) epssize = 3;
    238         else       epssize = 6;
    239 
    240         /*Fetch number of nodes and dof for this finite element*/
    241         int vnumnodes = element->NumberofNodesVelocity();
    242         int pnumnodes = element->NumberofNodesPressure();
    243         int numdof    = vnumnodes*dim + pnumnodes;
    244 
    245         /*Initialize Jacobian with regular FS (first part of the Gateau derivative)*/
    246         element->FindParam(&incomplete_adjoint,InversionIncompleteAdjointEnum);
    247         StressbalanceAnalysis* analysis = new StressbalanceAnalysis();
    248         ElementMatrix* Ke=analysis->CreateKMatrix(element);
    249         delete analysis;
    250         if(incomplete_adjoint) return Ke;
    251 
    252         /*Retrieve all inputs and parameters*/
    253         element->GetVerticesCoordinates(&xyz_list);
    254         Input* vx_input = element->GetInput(VxEnum);_assert_(vx_input);
    255         Input* vy_input = element->GetInput(VyEnum);_assert_(vy_input);
    256         Input* vz_input = NULL;
    257         if(dim==3){
    258                 vz_input = element->GetInput(VzEnum);
    259         }
    260         else{
    261                 _error_("Not implemented yet");
    262         }
    263 
    264         /*Allocate dbasis*/
    265         IssmDouble* dbasis = xNew<IssmDouble>(dim*vnumnodes);
    266 
    267         /* Start  looping on the number of gaussian points: */
    268         Gauss* gauss=element->NewGauss(5);
    269         for(int ig=gauss->begin();ig<gauss->end();ig++){
    270                 gauss->GaussPoint(ig);
    271 
    272                 element->JacobianDeterminant(&Jdet,xyz_list,gauss);
    273                 element->NodalFunctionsDerivatives(dbasis,xyz_list,gauss);
    274 
    275                 element->StrainRateHO(&epsilon[0],xyz_list,gauss,vx_input,vy_input);
    276                 element->ViscosityFSDerivativeEpsSquare(&mu_prime,&epsilon[0]);
    277                 eps1[0]=epsilon[0];   eps2[0]=epsilon[2];   eps3[0]=epsilon[3];
    278                 eps1[1]=epsilon[2];   eps2[1]=epsilon[1];   eps3[1]=epsilon[4];
    279                 eps1[2]=epsilon[3];   eps2[2]=epsilon[4];   eps3[2]= -epsilon[0] -epsilon[1];
    280 
    281                 for(int i=0;i<vnumnodes;i++){
    282                         for(int j=0;j<vnumnodes;j++){
    283                                 eps1dotdphii=eps1[0]*dbasis[0*vnumnodes+i]+eps1[1]*dbasis[1*vnumnodes+i]+eps1[2]*dbasis[2*vnumnodes+i];
    284                                 eps1dotdphij=eps1[0]*dbasis[0*vnumnodes+j]+eps1[1]*dbasis[1*vnumnodes+j]+eps1[2]*dbasis[2*vnumnodes+j];
    285                                 eps2dotdphii=eps2[0]*dbasis[0*vnumnodes+i]+eps2[1]*dbasis[1*vnumnodes+i]+eps2[2]*dbasis[2*vnumnodes+i];
    286                                 eps2dotdphij=eps2[0]*dbasis[0*vnumnodes+j]+eps2[1]*dbasis[1*vnumnodes+j]+eps2[2]*dbasis[2*vnumnodes+j];
    287                                 eps3dotdphii=eps3[0]*dbasis[0*vnumnodes+i]+eps3[1]*dbasis[1*vnumnodes+i]+eps3[2]*dbasis[2*vnumnodes+i];
    288                                 eps3dotdphij=eps3[0]*dbasis[0*vnumnodes+j]+eps3[1]*dbasis[1*vnumnodes+j]+eps3[2]*dbasis[2*vnumnodes+j];
    289 
    290                                 Ke->values[numdof*(4*i+0)+4*j+0]+=gauss->weight*Jdet*2*mu_prime*eps1dotdphij*eps1dotdphii;
    291                                 Ke->values[numdof*(4*i+0)+4*j+1]+=gauss->weight*Jdet*2*mu_prime*eps2dotdphij*eps1dotdphii;
    292                                 Ke->values[numdof*(4*i+0)+4*j+2]+=gauss->weight*Jdet*2*mu_prime*eps3dotdphij*eps1dotdphii;
    293 
    294                                 Ke->values[numdof*(4*i+1)+4*j+0]+=gauss->weight*Jdet*2*mu_prime*eps1dotdphij*eps2dotdphii;
    295                                 Ke->values[numdof*(4*i+1)+4*j+1]+=gauss->weight*Jdet*2*mu_prime*eps2dotdphij*eps2dotdphii;
    296                                 Ke->values[numdof*(4*i+1)+4*j+2]+=gauss->weight*Jdet*2*mu_prime*eps3dotdphij*eps2dotdphii;
    297 
    298                                 Ke->values[numdof*(4*i+2)+4*j+0]+=gauss->weight*Jdet*2*mu_prime*eps1dotdphij*eps3dotdphii;
    299                                 Ke->values[numdof*(4*i+2)+4*j+1]+=gauss->weight*Jdet*2*mu_prime*eps2dotdphij*eps3dotdphii;
    300                                 Ke->values[numdof*(4*i+2)+4*j+2]+=gauss->weight*Jdet*2*mu_prime*eps3dotdphij*eps3dotdphii;
    301                         }
    302                 }
    303         }
    304 
    305         /*Transform Coordinate System*/
    306         element->TransformStiffnessMatrixCoord(Ke,XYZEnum);
    307 
    308         /*Clean up and return*/
    309         delete gauss;
    310         xDelete<IssmDouble>(dbasis);
    311         xDelete<IssmDouble>(xyz_list);
    312312        return Ke;
    313313}/*}}}*/
     
    567567        return pe;
    568568}/*}}}*/
     569ElementVector* AdjointHorizAnalysis::CreatePVectorL1L2(Element* element){/*{{{*/
     570
     571        /*Same as SSA*/
     572        return this->CreatePVectorSSA(element);
     573}/*}}}*/
    569574ElementVector* AdjointHorizAnalysis::CreatePVectorHO(Element* element){/*{{{*/
    570575
     
    10421047        return pe;
    10431048}/*}}}*/
    1044 ElementVector* AdjointHorizAnalysis::CreatePVectorL1L2(Element* element){/*{{{*/
    1045 
    1046         /*Same as SSA*/
    1047         return this->CreatePVectorSSA(element);
    1048 }/*}}}*/
    1049 void AdjointHorizAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
     1049void           AdjointHorizAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
    10501050           _error_("not implemented yet");
    10511051}/*}}}*/
    1052 void AdjointHorizAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
     1052void           AdjointHorizAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
    10531053        /*The gradient of the cost function is calculated in 2 parts.
    10541054         *
     
    11381138                         
    11391139}/*}}}*/
    1140 void AdjointHorizAnalysis::GradientJDragGradient(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
    1141 
    1142         /*return if floating (gradient is 0)*/
    1143         if(element->IsFloating()) return;
    1144 
    1145         /*Intermediaries*/
    1146         int      domaintype,dim;
    1147         Element* basalelement;
    1148 
    1149         /*Get basal element*/
    1150         element->FindParam(&domaintype,DomainTypeEnum);
    1151         switch(domaintype){
    1152                 case Domain2DhorizontalEnum:
    1153                         basalelement = element;
    1154                         dim          = 2;
    1155                         break;
    1156                 case Domain2DverticalEnum:
    1157                         if(!element->IsOnBase()) return;
    1158                         basalelement = element->SpawnBasalElement();
    1159                         dim          = 1;
    1160                         break;
    1161                 case Domain3DEnum:
    1162                         if(!element->IsOnBase()) return;
    1163                         basalelement = element->SpawnBasalElement();
    1164                         dim          = 2;
    1165                         break;
    1166                 default: _error_("mesh "<<EnumToStringx(domaintype)<<" not supported yet");
    1167         }
    1168 
    1169         /*Intermediaries*/
    1170         IssmDouble Jdet,weight;
    1171         IssmDouble dk[3];
    1172         IssmDouble *xyz_list= NULL;
    1173 
    1174         /*Fetch number of vertices for this finite element*/
    1175         int numvertices = basalelement->GetNumberOfVertices();
    1176 
    1177         /*Initialize some vectors*/
    1178         IssmDouble* dbasis        = xNew<IssmDouble>(2*numvertices);
    1179         IssmDouble* ge            = xNewZeroInit<IssmDouble>(numvertices);
    1180         int*        vertexpidlist = xNew<int>(numvertices);
    1181 
    1182         /*Retrieve all inputs we will be needing: */
    1183         basalelement->GetVerticesCoordinates(&xyz_list);
    1184         basalelement->GradientIndexing(&vertexpidlist[0],control_index);
    1185         Input* dragcoefficient_input = basalelement->GetInput(FrictionCoefficientEnum);                _assert_(dragcoefficient_input);
    1186         Input* weights_input         = basalelement->GetInput(InversionCostFunctionsCoefficientsEnum); _assert_(weights_input);
    1187 
    1188         /* Start  looping on the number of gaussian points: */
    1189         Gauss* gauss=basalelement->NewGauss(2);
    1190         for(int ig=gauss->begin();ig<gauss->end();ig++){
    1191                 gauss->GaussPoint(ig);
    1192 
    1193                 basalelement->JacobianDeterminant(&Jdet,xyz_list,gauss);
    1194                 basalelement->NodalFunctionsP1Derivatives(dbasis,xyz_list,gauss);
    1195                 weights_input->GetInputValue(&weight,gauss,DragCoefficientAbsGradientEnum);
    1196 
    1197                 /*Build alpha_complement_list: */
    1198                 dragcoefficient_input->GetInputDerivativeValue(&dk[0],xyz_list,gauss);
    1199 
    1200                 /*Build gradient vector (actually -dJ/ddrag): */
    1201                 for(int i=0;i<numvertices;i++){
    1202                         if(dim==2){
    1203                                 ge[i]+=-weight*Jdet*gauss->weight*(dbasis[0*numvertices+i]*dk[0]+dbasis[1*numvertices+i]*dk[1]);
    1204                         }
    1205                         else{
    1206                                 ge[i]+=-weight*Jdet*gauss->weight*dbasis[0*numvertices+i]*dk[0];
    1207                         }
    1208                         _assert_(!xIsNan<IssmDouble>(ge[i]));
    1209                 }
    1210         }
    1211         gradient->SetValues(numvertices,vertexpidlist,ge,ADD_VAL);
    1212 
    1213         /*Clean up and return*/
    1214         xDelete<IssmDouble>(xyz_list);
    1215         xDelete<IssmDouble>(dbasis);
    1216         xDelete<IssmDouble>(ge);
    1217         xDelete<int>(vertexpidlist);
    1218         delete gauss;
    1219         if(domaintype!=Domain2DhorizontalEnum){basalelement->DeleteMaterials(); delete basalelement;};
    1220 
    1221 }/*}}}*/
    1222 void AdjointHorizAnalysis::GradientJBbarGradient(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
     1140void           AdjointHorizAnalysis::GradientJBbarFS(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
     1141        /*WARNING: We use SSA as an estimate for now*/
     1142        this->GradientJBbarSSA(element,gradient,control_index);
     1143}/*}}}*/
     1144void           AdjointHorizAnalysis::GradientJBbarGradient(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
    12231145
    12241146        /*Intermediaries*/
     
    12951217        if(domaintype!=Domain2DhorizontalEnum){basalelement->DeleteMaterials(); delete basalelement;};
    12961218}/*}}}*/
    1297 void AdjointHorizAnalysis::GradientJBGradient(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
     1219void           AdjointHorizAnalysis::GradientJBbarL1L2(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
     1220
     1221           /*Same as SSA*/
     1222           return this->GradientJBbarSSA(element,gradient,control_index);
     1223}/*}}}*/
     1224void           AdjointHorizAnalysis::GradientJBbarHO(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
     1225
     1226        /*WARNING: We use SSA as an estimate for now*/
     1227        this->GradientJBbarSSA(element,gradient,control_index);
     1228}/*}}}*/
     1229void           AdjointHorizAnalysis::GradientJBbarSSA(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
     1230
     1231        /*Intermediaries*/
     1232        int      domaintype,dim;
     1233        Element* basalelement;
     1234
     1235        /*Get basal element*/
     1236        element->FindParam(&domaintype,DomainTypeEnum);
     1237        switch(domaintype){
     1238                case Domain2DhorizontalEnum:
     1239                        basalelement = element;
     1240                        dim          = 2;
     1241                        break;
     1242                case Domain2DverticalEnum:
     1243                        if(!element->IsOnBase()) return;
     1244                        basalelement = element->SpawnBasalElement();
     1245                        dim          = 1;
     1246                        break;
     1247                case Domain3DEnum:
     1248                        if(!element->IsOnBase()) return;
     1249                        basalelement = element->SpawnBasalElement();
     1250                        dim          = 2;
     1251                        break;
     1252                default: _error_("mesh "<<EnumToStringx(domaintype)<<" not supported yet");
     1253        }
     1254
     1255        /*Intermediaries*/
     1256        IssmDouble Jdet,weight;
     1257        IssmDouble thickness,dmudB;
     1258        IssmDouble dvx[3],dvy[3],dadjx[3],dadjy[3];
     1259        IssmDouble *xyz_list= NULL;
     1260
     1261        /*Fetch number of vertices for this finite element*/
     1262        int numvertices = basalelement->GetNumberOfVertices();
     1263
     1264        /*Initialize some vectors*/
     1265        IssmDouble* basis         = xNew<IssmDouble>(numvertices);
     1266        IssmDouble* ge            = xNewZeroInit<IssmDouble>(numvertices);
     1267        int*        vertexpidlist = xNew<int>(numvertices);
     1268
     1269        /*Retrieve all inputs we will be needing: */
     1270        basalelement->GetVerticesCoordinates(&xyz_list);
     1271        basalelement->GradientIndexing(&vertexpidlist[0],control_index);
     1272        Input* thickness_input = basalelement->GetInput(ThicknessEnum);             _assert_(thickness_input);
     1273        Input* vx_input        = basalelement->GetInput(VxEnum);                    _assert_(vx_input);
     1274        Input* vy_input        = basalelement->GetInput(VyEnum);                    _assert_(vy_input);
     1275        Input* adjointx_input  = basalelement->GetInput(AdjointxEnum);              _assert_(adjointx_input);
     1276        Input* adjointy_input  = basalelement->GetInput(AdjointyEnum);              _assert_(adjointy_input);
     1277        Input* rheologyb_input = basalelement->GetInput(MaterialsRheologyBbarEnum); _assert_(rheologyb_input);
     1278
     1279        /* Start  looping on the number of gaussian points: */
     1280        Gauss* gauss=basalelement->NewGauss(4);
     1281        for(int ig=gauss->begin();ig<gauss->end();ig++){
     1282                gauss->GaussPoint(ig);
     1283
     1284                thickness_input->GetInputValue(&thickness,gauss);
     1285                vx_input->GetInputDerivativeValue(&dvx[0],xyz_list,gauss);
     1286                vy_input->GetInputDerivativeValue(&dvy[0],xyz_list,gauss);
     1287                adjointx_input->GetInputDerivativeValue(&dadjx[0],xyz_list,gauss);
     1288                adjointy_input->GetInputDerivativeValue(&dadjy[0],xyz_list,gauss);
     1289
     1290                basalelement->dViscositydBSSA(&dmudB,dim,xyz_list,gauss,vx_input,vy_input);
     1291
     1292                basalelement->JacobianDeterminant(&Jdet,xyz_list,gauss);
     1293                basalelement->NodalFunctionsP1(basis,gauss);
     1294
     1295                /*Build gradient vector (actually -dJ/dB): */
     1296                for(int i=0;i<numvertices;i++){
     1297                        ge[i]+=-dmudB*thickness*(
     1298                                                (2*dvx[0]+dvy[1])*2*dadjx[0]+(dvx[1]+dvy[0])*(dadjx[1]+dadjy[0])+(2*dvy[1]+dvx[0])*2*dadjy[1]
     1299                                                )*Jdet*gauss->weight*basis[i];
     1300                        _assert_(!xIsNan<IssmDouble>(ge[i]));
     1301                }
     1302        }
     1303        gradient->SetValues(numvertices,vertexpidlist,ge,ADD_VAL);
     1304
     1305        /*Clean up and return*/
     1306        xDelete<IssmDouble>(xyz_list);
     1307        xDelete<IssmDouble>(basis);
     1308        xDelete<IssmDouble>(ge);
     1309        xDelete<int>(vertexpidlist);
     1310        delete gauss;
     1311        if(domaintype!=Domain2DhorizontalEnum){basalelement->DeleteMaterials(); delete basalelement;};
     1312}/*}}}*/
     1313void           AdjointHorizAnalysis::GradientJBFS(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
     1314        /*WARNING: We use HO as an estimate for now*/
     1315        this->GradientJBHO(element,gradient,control_index);
     1316}/*}}}*/
     1317void           AdjointHorizAnalysis::GradientJBGradient(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
    12981318
    12991319        /*Intermediaries*/
     
    13611381        delete gauss;
    13621382}/*}}}*/
    1363 void AdjointHorizAnalysis::GradientJDragSSA(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
    1364 
    1365         /*return if floating (gradient is 0)*/
    1366         if(element->IsFloating()) return;
     1383void           AdjointHorizAnalysis::GradientJBHO(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
     1384        /*Intermediaries*/
     1385        int      domaintype,dim;
     1386
     1387        /*Get domaintype*/
     1388        element->FindParam(&domaintype,DomainTypeEnum);
     1389
     1390        /*Intermediaries*/
     1391        IssmDouble Jdet,weight;
     1392        IssmDouble thickness,dmudB;
     1393        IssmDouble dvx[3],dvy[3],dadjx[3],dadjy[3];
     1394        IssmDouble *xyz_list= NULL;
     1395
     1396        /*Fetch number of vertices for this finite element*/
     1397        int numvertices = element->GetNumberOfVertices();
     1398
     1399        /*Initialize some vectors*/
     1400        IssmDouble* basis         = xNew<IssmDouble>(numvertices);
     1401        IssmDouble* ge            = xNewZeroInit<IssmDouble>(numvertices);
     1402        int*        vertexpidlist = xNew<int>(numvertices);
     1403
     1404        /*Retrieve all inputs we will be needing: */
     1405        element->GetVerticesCoordinates(&xyz_list);
     1406        element->GradientIndexing(&vertexpidlist[0],control_index);
     1407        Input* thickness_input = element->GetInput(ThicknessEnum);             _assert_(thickness_input);
     1408        Input* vx_input        = element->GetInput(VxEnum);                    _assert_(vx_input);
     1409        Input* vy_input        = NULL;
     1410        Input* adjointx_input  = element->GetInput(AdjointxEnum);              _assert_(adjointx_input);
     1411        Input* adjointy_input  = NULL;
     1412        Input* rheologyb_input = element->GetInput(MaterialsRheologyBEnum); _assert_(rheologyb_input);
     1413        if(domaintype!=Domain2DverticalEnum){
     1414                vy_input        = element->GetInput(VyEnum);                   _assert_(vy_input);
     1415                adjointy_input  = element->GetInput(AdjointyEnum);             _assert_(adjointy_input);
     1416        }
     1417        /* Start  looping on the number of gaussian points: */
     1418        Gauss* gauss=element->NewGauss(4);
     1419        for(int ig=gauss->begin();ig<gauss->end();ig++){
     1420                gauss->GaussPoint(ig);
     1421
     1422                thickness_input->GetInputValue(&thickness,gauss);
     1423                vx_input->GetInputDerivativeValue(&dvx[0],xyz_list,gauss);
     1424                adjointx_input->GetInputDerivativeValue(&dadjx[0],xyz_list,gauss);
     1425                dim=2;
     1426                if(domaintype!=Domain2DverticalEnum){
     1427                        adjointy_input->GetInputDerivativeValue(&dadjy[0],xyz_list, gauss);
     1428                        vy_input->GetInputDerivativeValue(&dvy[0],xyz_list,gauss);
     1429                        dim=3;
     1430                }
     1431
     1432                element->dViscositydBHO(&dmudB,dim,xyz_list,gauss,vx_input,vy_input);
     1433
     1434                element->JacobianDeterminant(&Jdet,xyz_list,gauss);
     1435                element->NodalFunctionsP1(basis,gauss);
     1436
     1437                /*Build gradient vector (actually -dJ/dB): */
     1438                for(int i=0;i<numvertices;i++){
     1439                        if(domaintype!=Domain2DverticalEnum){
     1440                                ge[i]+=-dmudB*thickness*(
     1441                                                        (2*dvx[0]+dvy[1])*2*dadjx[0]+(dvx[1]+dvy[0])*(dadjx[1]+dadjy[0])+(2*dvy[1]+dvx[0])*2*dadjy[1]
     1442                                                        )*Jdet*gauss->weight*basis[i];
     1443                        }
     1444                        else{
     1445                                ge[i]+=-dmudB*thickness*4*dvx[0]*dadjx[0]*Jdet*gauss->weight*basis[i];
     1446                        }
     1447                        _assert_(!xIsNan<IssmDouble>(ge[i]));
     1448                }
     1449        }
     1450        gradient->SetValues(numvertices,vertexpidlist,ge,ADD_VAL);
     1451
     1452        /*Clean up and return*/
     1453        xDelete<IssmDouble>(xyz_list);
     1454        xDelete<IssmDouble>(basis);
     1455        xDelete<IssmDouble>(ge);
     1456        xDelete<int>(vertexpidlist);
     1457        delete gauss;
     1458}/*}}}*/
     1459void           AdjointHorizAnalysis::GradientJBSSA(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
    13671460
    13681461        /*Intermediaries*/
     
    13921485        /*Intermediaries*/
    13931486        IssmDouble Jdet,weight;
    1394         IssmDouble drag,dalpha2dk;
    1395         IssmDouble vx,vy,lambda,mu;
     1487        IssmDouble thickness,dmudB;
     1488        IssmDouble dvx[3],dvy[3],dadjx[3],dadjy[3];
    13961489        IssmDouble *xyz_list= NULL;
    13971490
     
    14041497        int*        vertexpidlist = xNew<int>(numvertices);
    14051498
    1406         /*Build friction element, needed later: */
    1407         Friction* friction=new Friction(basalelement,dim);
    1408 
    14091499        /*Retrieve all inputs we will be needing: */
    14101500        basalelement->GetVerticesCoordinates(&xyz_list);
    14111501        basalelement->GradientIndexing(&vertexpidlist[0],control_index);
    1412         Input* vx_input        = basalelement->GetInput(VxEnum);                   _assert_(vx_input);
    1413         Input* vy_input        = basalelement->GetInput(VyEnum);                   _assert_(vy_input);
    1414         Input* adjointx_input  = basalelement->GetInput(AdjointxEnum);             _assert_(adjointx_input);
    1415         Input* adjointy_input  = basalelement->GetInput(AdjointyEnum);             _assert_(adjointy_input);
    1416         Input* dragcoeff_input = basalelement->GetInput(FrictionCoefficientEnum);  _assert_(dragcoeff_input);
     1502        Input* thickness_input = basalelement->GetInput(ThicknessEnum);             _assert_(thickness_input);
     1503        Input* vx_input        = basalelement->GetInput(VxEnum);                    _assert_(vx_input);
     1504        Input* vy_input        = basalelement->GetInput(VyEnum);                    _assert_(vy_input);
     1505        Input* adjointx_input  = basalelement->GetInput(AdjointxEnum);              _assert_(adjointx_input);
     1506        Input* adjointy_input  = basalelement->GetInput(AdjointyEnum);              _assert_(adjointy_input);
     1507        Input* rheologyb_input = basalelement->GetInput(MaterialsRheologyBEnum); _assert_(rheologyb_input);
    14171508
    14181509        /* Start  looping on the number of gaussian points: */
     
    14211512                gauss->GaussPoint(ig);
    14221513
    1423                 adjointx_input->GetInputValue(&lambda, gauss);
    1424                 adjointy_input->GetInputValue(&mu, gauss);
    1425                 vx_input->GetInputValue(&vx,gauss);
    1426                 vy_input->GetInputValue(&vy,gauss);
    1427                 dragcoeff_input->GetInputValue(&drag, gauss);
    1428 
    1429                 friction->GetAlphaComplement(&dalpha2dk,gauss);
     1514                thickness_input->GetInputValue(&thickness,gauss);
     1515                vx_input->GetInputDerivativeValue(&dvx[0],xyz_list,gauss);
     1516                vy_input->GetInputDerivativeValue(&dvy[0],xyz_list,gauss);
     1517                adjointx_input->GetInputDerivativeValue(&dadjx[0],xyz_list,gauss);
     1518                adjointy_input->GetInputDerivativeValue(&dadjy[0],xyz_list,gauss);
     1519
     1520                basalelement->dViscositydBSSA(&dmudB,dim,xyz_list,gauss,vx_input,vy_input);
    14301521
    14311522                basalelement->JacobianDeterminant(&Jdet,xyz_list,gauss);
    14321523                basalelement->NodalFunctionsP1(basis,gauss);
    14331524
    1434                 /*Build gradient vector (actually -dJ/dD): */
     1525                /*Build gradient vector (actually -dJ/dB): */
    14351526                for(int i=0;i<numvertices;i++){
    1436                         ge[i]+=-2.*drag*dalpha2dk*((lambda*vx+mu*vy))*Jdet*gauss->weight*basis[i];
     1527                        ge[i]+=-dmudB*thickness*(
     1528                                                (2*dvx[0]+dvy[1])*2*dadjx[0]+(dvx[1]+dvy[0])*(dadjx[1]+dadjy[0])+(2*dvy[1]+dvx[0])*2*dadjy[1]
     1529                                                )*Jdet*gauss->weight*basis[i];
    14371530                        _assert_(!xIsNan<IssmDouble>(ge[i]));
    14381531                }
     
    14461539        xDelete<int>(vertexpidlist);
    14471540        delete gauss;
    1448         delete friction;
    14491541        if(domaintype!=Domain2DhorizontalEnum){basalelement->DeleteMaterials(); delete basalelement;};
    14501542}/*}}}*/
    1451 void AdjointHorizAnalysis::GradientJDragL1L2(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
    1452 
    1453         /*Same as SSA*/
    1454         return this->GradientJDragSSA(element,gradient,control_index);
    1455 }/*}}}*/
    1456 void AdjointHorizAnalysis::GradientJDragHO(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
    1457 
    1458         /*return if floating or not on bed (gradient is 0)*/
     1543void           AdjointHorizAnalysis::GradientJDragGradient(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
     1544
     1545        /*return if floating (gradient is 0)*/
    14591546        if(element->IsFloating()) return;
    1460         if(!element->IsOnBase()) return;
     1547
     1548        /*Intermediaries*/
     1549        int      domaintype,dim;
     1550        Element* basalelement;
     1551
     1552        /*Get basal element*/
     1553        element->FindParam(&domaintype,DomainTypeEnum);
     1554        switch(domaintype){
     1555                case Domain2DhorizontalEnum:
     1556                        basalelement = element;
     1557                        dim          = 2;
     1558                        break;
     1559                case Domain2DverticalEnum:
     1560                        if(!element->IsOnBase()) return;
     1561                        basalelement = element->SpawnBasalElement();
     1562                        dim          = 1;
     1563                        break;
     1564                case Domain3DEnum:
     1565                        if(!element->IsOnBase()) return;
     1566                        basalelement = element->SpawnBasalElement();
     1567                        dim          = 2;
     1568                        break;
     1569                default: _error_("mesh "<<EnumToStringx(domaintype)<<" not supported yet");
     1570        }
    14611571
    14621572        /*Intermediaries*/
    14631573        IssmDouble Jdet,weight;
    1464         IssmDouble drag,dalpha2dk;
    1465         IssmDouble vx,vy,lambda,mu;
    1466         IssmDouble *xyz_list_base= NULL;
    1467 
    1468         int      domaintype,dim;
    1469         element->FindParam(&domaintype,DomainTypeEnum);
     1574        IssmDouble dk[3];
     1575        IssmDouble *xyz_list= NULL;
     1576
    14701577        /*Fetch number of vertices for this finite element*/
    1471         int numvertices = element->GetNumberOfVertices();
     1578        int numvertices = basalelement->GetNumberOfVertices();
    14721579
    14731580        /*Initialize some vectors*/
    1474         IssmDouble* basis         = xNew<IssmDouble>(numvertices);
     1581        IssmDouble* dbasis        = xNew<IssmDouble>(2*numvertices);
    14751582        IssmDouble* ge            = xNewZeroInit<IssmDouble>(numvertices);
    14761583        int*        vertexpidlist = xNew<int>(numvertices);
    14771584
    1478         /*Build friction element, needed later: */
    1479         if(domaintype!=Domain2DverticalEnum) dim=3;
    1480         else dim=2;
    1481         Friction* friction=new Friction(element,dim);
    1482 
    14831585        /*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         }
     1586        basalelement->GetVerticesCoordinates(&xyz_list);
     1587        basalelement->GradientIndexing(&vertexpidlist[0],control_index);
     1588        Input* dragcoefficient_input = basalelement->GetInput(FrictionCoefficientEnum);                _assert_(dragcoefficient_input);
     1589        Input* weights_input         = basalelement->GetInput(InversionCostFunctionsCoefficientsEnum); _assert_(weights_input);
     1590
    14951591        /* Start  looping on the number of gaussian points: */
    1496         Gauss* gauss=element->NewGaussBase(4);
     1592        Gauss* gauss=basalelement->NewGauss(2);
    14971593        for(int ig=gauss->begin();ig<gauss->end();ig++){
    14981594                gauss->GaussPoint(ig);
    14991595
    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): */
     1596                basalelement->JacobianDeterminant(&Jdet,xyz_list,gauss);
     1597                basalelement->NodalFunctionsP1Derivatives(dbasis,xyz_list,gauss);
     1598                weights_input->GetInputValue(&weight,gauss,DragCoefficientAbsGradientEnum);
     1599
     1600                /*Build alpha_complement_list: */
     1601                dragcoefficient_input->GetInputDerivativeValue(&dk[0],xyz_list,gauss);
     1602
     1603                /*Build gradient vector (actually -dJ/ddrag): */
    15141604                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];
     1605                        if(dim==2){
     1606                                ge[i]+=-weight*Jdet*gauss->weight*(dbasis[0*numvertices+i]*dk[0]+dbasis[1*numvertices+i]*dk[1]);
     1607                        }
     1608                        else{
     1609                                ge[i]+=-weight*Jdet*gauss->weight*dbasis[0*numvertices+i]*dk[0];
     1610                        }
    15171611                        _assert_(!xIsNan<IssmDouble>(ge[i]));
    15181612                }
     
    15211615
    15221616        /*Clean up and return*/
    1523         xDelete<IssmDouble>(xyz_list_base);
    1524         xDelete<IssmDouble>(basis);
     1617        xDelete<IssmDouble>(xyz_list);
     1618        xDelete<IssmDouble>(dbasis);
    15251619        xDelete<IssmDouble>(ge);
    15261620        xDelete<int>(vertexpidlist);
    15271621        delete gauss;
    1528         delete friction;
    1529 }/*}}}*/
    1530 void AdjointHorizAnalysis::GradientJDragFS(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
     1622        if(domaintype!=Domain2DhorizontalEnum){basalelement->DeleteMaterials(); delete basalelement;};
     1623
     1624}/*}}}*/
     1625void           AdjointHorizAnalysis::GradientJDragFS(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
    15311626
    15321627        /*return if floating or not on bed (gradient is 0)*/
     
    16241719        delete friction;
    16251720}/*}}}*/
    1626 void AdjointHorizAnalysis::GradientJBbarSSA(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
     1721void           AdjointHorizAnalysis::GradientJDragL1L2(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
     1722
     1723        /*Same as SSA*/
     1724        return this->GradientJDragSSA(element,gradient,control_index);
     1725}/*}}}*/
     1726void           AdjointHorizAnalysis::GradientJDragHO(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
     1727
     1728        /*return if floating or not on bed (gradient is 0)*/
     1729        if(element->IsFloating()) return;
     1730        if(!element->IsOnBase()) return;
     1731
     1732        /*Intermediaries*/
     1733        IssmDouble Jdet,weight;
     1734        IssmDouble drag,dalpha2dk;
     1735        IssmDouble vx,vy,lambda,mu;
     1736        IssmDouble *xyz_list_base= NULL;
     1737
     1738        int      domaintype,dim;
     1739        element->FindParam(&domaintype,DomainTypeEnum);
     1740        /*Fetch number of vertices for this finite element*/
     1741        int numvertices = element->GetNumberOfVertices();
     1742
     1743        /*Initialize some vectors*/
     1744        IssmDouble* basis         = xNew<IssmDouble>(numvertices);
     1745        IssmDouble* ge            = xNewZeroInit<IssmDouble>(numvertices);
     1746        int*        vertexpidlist = xNew<int>(numvertices);
     1747
     1748        /*Build friction element, needed later: */
     1749        if(domaintype!=Domain2DverticalEnum) dim=3;
     1750        else dim=2;
     1751        Friction* friction=new Friction(element,dim);
     1752
     1753        /*Retrieve all inputs we will be needing: */
     1754        element->GetVerticesCoordinatesBase(&xyz_list_base);
     1755        element->GradientIndexing(&vertexpidlist[0],control_index);
     1756        Input* vx_input        = element->GetInput(VxEnum);                   _assert_(vx_input);
     1757        Input* vy_input        = NULL;
     1758        Input* adjointx_input  = element->GetInput(AdjointxEnum);             _assert_(adjointx_input);
     1759        Input* adjointy_input  = NULL;
     1760        Input* dragcoeff_input = element->GetInput(FrictionCoefficientEnum);  _assert_(dragcoeff_input);
     1761        if(domaintype!=Domain2DverticalEnum){
     1762                vy_input        = element->GetInput(VyEnum);                   _assert_(vy_input);
     1763                adjointy_input  = element->GetInput(AdjointyEnum);             _assert_(adjointy_input);
     1764        }
     1765        /* Start  looping on the number of gaussian points: */
     1766        Gauss* gauss=element->NewGaussBase(4);
     1767        for(int ig=gauss->begin();ig<gauss->end();ig++){
     1768                gauss->GaussPoint(ig);
     1769
     1770                adjointx_input->GetInputValue(&lambda, gauss);
     1771                vx_input->GetInputValue(&vx,gauss);
     1772                if(domaintype!=Domain2DverticalEnum){
     1773                        adjointy_input->GetInputValue(&mu, gauss);
     1774                        vy_input->GetInputValue(&vy,gauss);
     1775                }
     1776                dragcoeff_input->GetInputValue(&drag, gauss);
     1777
     1778                friction->GetAlphaComplement(&dalpha2dk,gauss);
     1779
     1780                element->JacobianDeterminantBase(&Jdet,xyz_list_base,gauss);
     1781                element->NodalFunctionsP1(basis,gauss);
     1782
     1783                /*Build gradient vector (actually -dJ/dD): */
     1784                for(int i=0;i<numvertices;i++){
     1785                        if(domaintype!=Domain2DverticalEnum) ge[i]+=-2.*drag*dalpha2dk*((lambda*vx+mu*vy))*Jdet*gauss->weight*basis[i];
     1786                        else ge[i]+=-2.*drag*dalpha2dk*(lambda*vx)*Jdet*gauss->weight*basis[i];
     1787                        _assert_(!xIsNan<IssmDouble>(ge[i]));
     1788                }
     1789        }
     1790        gradient->SetValues(numvertices,vertexpidlist,ge,ADD_VAL);
     1791
     1792        /*Clean up and return*/
     1793        xDelete<IssmDouble>(xyz_list_base);
     1794        xDelete<IssmDouble>(basis);
     1795        xDelete<IssmDouble>(ge);
     1796        xDelete<int>(vertexpidlist);
     1797        delete gauss;
     1798        delete friction;
     1799}/*}}}*/
     1800void           AdjointHorizAnalysis::GradientJDragSSA(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
     1801
     1802        /*return if floating (gradient is 0)*/
     1803        if(element->IsFloating()) return;
    16271804
    16281805        /*Intermediaries*/
     
    16521829        /*Intermediaries*/
    16531830        IssmDouble Jdet,weight;
    1654         IssmDouble thickness,dmudB;
     1831        IssmDouble drag,dalpha2dk;
     1832        IssmDouble vx,vy,lambda,mu;
     1833        IssmDouble *xyz_list= NULL;
     1834
     1835        /*Fetch number of vertices for this finite element*/
     1836        int numvertices = basalelement->GetNumberOfVertices();
     1837
     1838        /*Initialize some vectors*/
     1839        IssmDouble* basis         = xNew<IssmDouble>(numvertices);
     1840        IssmDouble* ge            = xNewZeroInit<IssmDouble>(numvertices);
     1841        int*        vertexpidlist = xNew<int>(numvertices);
     1842
     1843        /*Build friction element, needed later: */
     1844        Friction* friction=new Friction(basalelement,dim);
     1845
     1846        /*Retrieve all inputs we will be needing: */
     1847        basalelement->GetVerticesCoordinates(&xyz_list);
     1848        basalelement->GradientIndexing(&vertexpidlist[0],control_index);
     1849        Input* vx_input        = basalelement->GetInput(VxEnum);                   _assert_(vx_input);
     1850        Input* vy_input        = basalelement->GetInput(VyEnum);                   _assert_(vy_input);
     1851        Input* adjointx_input  = basalelement->GetInput(AdjointxEnum);             _assert_(adjointx_input);
     1852        Input* adjointy_input  = basalelement->GetInput(AdjointyEnum);             _assert_(adjointy_input);
     1853        Input* dragcoeff_input = basalelement->GetInput(FrictionCoefficientEnum);  _assert_(dragcoeff_input);
     1854
     1855        /* Start  looping on the number of gaussian points: */
     1856        Gauss* gauss=basalelement->NewGauss(4);
     1857        for(int ig=gauss->begin();ig<gauss->end();ig++){
     1858                gauss->GaussPoint(ig);
     1859
     1860                adjointx_input->GetInputValue(&lambda, gauss);
     1861                adjointy_input->GetInputValue(&mu, gauss);
     1862                vx_input->GetInputValue(&vx,gauss);
     1863                vy_input->GetInputValue(&vy,gauss);
     1864                dragcoeff_input->GetInputValue(&drag, gauss);
     1865
     1866                friction->GetAlphaComplement(&dalpha2dk,gauss);
     1867
     1868                basalelement->JacobianDeterminant(&Jdet,xyz_list,gauss);
     1869                basalelement->NodalFunctionsP1(basis,gauss);
     1870
     1871                /*Build gradient vector (actually -dJ/dD): */
     1872                for(int i=0;i<numvertices;i++){
     1873                        ge[i]+=-2.*drag*dalpha2dk*((lambda*vx+mu*vy))*Jdet*gauss->weight*basis[i];
     1874                        _assert_(!xIsNan<IssmDouble>(ge[i]));
     1875                }
     1876        }
     1877        gradient->SetValues(numvertices,vertexpidlist,ge,ADD_VAL);
     1878
     1879        /*Clean up and return*/
     1880        xDelete<IssmDouble>(xyz_list);
     1881        xDelete<IssmDouble>(basis);
     1882        xDelete<IssmDouble>(ge);
     1883        xDelete<int>(vertexpidlist);
     1884        delete gauss;
     1885        delete friction;
     1886        if(domaintype!=Domain2DhorizontalEnum){basalelement->DeleteMaterials(); delete basalelement;};
     1887}/*}}}*/
     1888void           AdjointHorizAnalysis::GradientJDSSA(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
     1889
     1890        /*Intermediaries*/
     1891        int      domaintype,dim;
     1892        Element* basalelement;
     1893
     1894        /*Get basal element*/
     1895        element->FindParam(&domaintype,DomainTypeEnum);
     1896        switch(domaintype){
     1897                case Domain2DhorizontalEnum:
     1898                        basalelement = element;
     1899                        dim          = 2;
     1900                        break;
     1901                case Domain2DverticalEnum:
     1902                        if(!element->IsOnBase()) return;
     1903                        basalelement = element->SpawnBasalElement();
     1904                        dim          = 1;
     1905                        break;
     1906                case Domain3DEnum:
     1907                        if(!element->IsOnBase()) return;
     1908                        basalelement = element->SpawnBasalElement();
     1909                        dim          = 2;
     1910                        break;
     1911                default: _error_("mesh "<<EnumToStringx(domaintype)<<" not supported yet");
     1912        }
     1913
     1914        /*Intermediaries*/
     1915        IssmDouble Jdet,weight;
     1916        IssmDouble thickness,dmudD;
    16551917        IssmDouble dvx[3],dvy[3],dadjx[3],dadjy[3];
    16561918        IssmDouble *xyz_list= NULL;
     
    16851947                adjointy_input->GetInputDerivativeValue(&dadjy[0],xyz_list,gauss);
    16861948
    1687                 basalelement->dViscositydBSSA(&dmudB,dim,xyz_list,gauss,vx_input,vy_input);
     1949                basalelement->dViscositydDSSA(&dmudD,dim,xyz_list,gauss,vx_input,vy_input);
    16881950
    16891951                basalelement->JacobianDeterminant(&Jdet,xyz_list,gauss);
    16901952                basalelement->NodalFunctionsP1(basis,gauss);
    16911953
    1692                 /*Build gradient vector (actually -dJ/dB): */
    16931954                for(int i=0;i<numvertices;i++){
    1694                         ge[i]+=-dmudB*thickness*(
     1955                        ge[i]+=-dmudD*thickness*(
    16951956                                                (2*dvx[0]+dvy[1])*2*dadjx[0]+(dvx[1]+dvy[0])*(dadjx[1]+dadjy[0])+(2*dvy[1]+dvx[0])*2*dadjy[1]
    16961957                                                )*Jdet*gauss->weight*basis[i];
     
    17081969        if(domaintype!=Domain2DhorizontalEnum){basalelement->DeleteMaterials(); delete basalelement;};
    17091970}/*}}}*/
    1710 void AdjointHorizAnalysis::GradientJBbarL1L2(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
    1711 
    1712            /*Same as SSA*/
    1713            return this->GradientJBbarSSA(element,gradient,control_index);
    1714 }/*}}}*/
    1715 void AdjointHorizAnalysis::GradientJBbarHO(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
    1716 
    1717         /*WARNING: We use SSA as an estimate for now*/
    1718         this->GradientJBbarSSA(element,gradient,control_index);
    1719 }/*}}}*/
    1720 void AdjointHorizAnalysis::GradientJBbarFS(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
    1721         /*WARNING: We use SSA as an estimate for now*/
    1722         this->GradientJBbarSSA(element,gradient,control_index);
    1723 }/*}}}*/
    1724 void 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 }/*}}}*/
    1808 void 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 }/*}}}*/
    1884 void 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 }/*}}}*/
    1888 void AdjointHorizAnalysis::GradientJDSSA(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
    1889 
    1890         /*Intermediaries*/
    1891         int      domaintype,dim;
    1892         Element* basalelement;
    1893 
    1894         /*Get basal element*/
    1895         element->FindParam(&domaintype,DomainTypeEnum);
    1896         switch(domaintype){
    1897                 case Domain2DhorizontalEnum:
    1898                         basalelement = element;
    1899                         dim          = 2;
    1900                         break;
    1901                 case Domain2DverticalEnum:
    1902                         if(!element->IsOnBase()) return;
    1903                         basalelement = element->SpawnBasalElement();
    1904                         dim          = 1;
    1905                         break;
    1906                 case Domain3DEnum:
    1907                         if(!element->IsOnBase()) return;
    1908                         basalelement = element->SpawnBasalElement();
    1909                         dim          = 2;
    1910                         break;
    1911                 default: _error_("mesh "<<EnumToStringx(domaintype)<<" not supported yet");
    1912         }
    1913 
    1914         /*Intermediaries*/
    1915         IssmDouble Jdet,weight;
    1916         IssmDouble thickness,dmudD;
    1917         IssmDouble dvx[3],dvy[3],dadjx[3],dadjy[3];
    1918         IssmDouble *xyz_list= NULL;
    1919 
    1920         /*Fetch number of vertices for this finite element*/
    1921         int numvertices = basalelement->GetNumberOfVertices();
    1922 
    1923         /*Initialize some vectors*/
    1924         IssmDouble* basis         = xNew<IssmDouble>(numvertices);
    1925         IssmDouble* ge            = xNewZeroInit<IssmDouble>(numvertices);
    1926         int*        vertexpidlist = xNew<int>(numvertices);
    1927 
    1928         /*Retrieve all inputs we will be needing: */
    1929         basalelement->GetVerticesCoordinates(&xyz_list);
    1930         basalelement->GradientIndexing(&vertexpidlist[0],control_index);
    1931         Input* thickness_input = basalelement->GetInput(ThicknessEnum);             _assert_(thickness_input);
    1932         Input* vx_input        = basalelement->GetInput(VxEnum);                    _assert_(vx_input);
    1933         Input* vy_input        = basalelement->GetInput(VyEnum);                    _assert_(vy_input);
    1934         Input* adjointx_input  = basalelement->GetInput(AdjointxEnum);              _assert_(adjointx_input);
    1935         Input* adjointy_input  = basalelement->GetInput(AdjointyEnum);              _assert_(adjointy_input);
    1936         Input* rheologyb_input = basalelement->GetInput(MaterialsRheologyBbarEnum); _assert_(rheologyb_input);
    1937 
    1938         /* Start  looping on the number of gaussian points: */
    1939         Gauss* gauss=basalelement->NewGauss(4);
    1940         for(int ig=gauss->begin();ig<gauss->end();ig++){
    1941                 gauss->GaussPoint(ig);
    1942 
    1943                 thickness_input->GetInputValue(&thickness,gauss);
    1944                 vx_input->GetInputDerivativeValue(&dvx[0],xyz_list,gauss);
    1945                 vy_input->GetInputDerivativeValue(&dvy[0],xyz_list,gauss);
    1946                 adjointx_input->GetInputDerivativeValue(&dadjx[0],xyz_list,gauss);
    1947                 adjointy_input->GetInputDerivativeValue(&dadjy[0],xyz_list,gauss);
    1948 
    1949                 basalelement->dViscositydDSSA(&dmudD,dim,xyz_list,gauss,vx_input,vy_input);
    1950 
    1951                 basalelement->JacobianDeterminant(&Jdet,xyz_list,gauss);
    1952                 basalelement->NodalFunctionsP1(basis,gauss);
    1953 
    1954                 for(int i=0;i<numvertices;i++){
    1955                         ge[i]+=-dmudD*thickness*(
    1956                                                 (2*dvx[0]+dvy[1])*2*dadjx[0]+(dvx[1]+dvy[0])*(dadjx[1]+dadjy[0])+(2*dvy[1]+dvx[0])*2*dadjy[1]
    1957                                                 )*Jdet*gauss->weight*basis[i];
    1958                         _assert_(!xIsNan<IssmDouble>(ge[i]));
    1959                 }
    1960         }
    1961         gradient->SetValues(numvertices,vertexpidlist,ge,ADD_VAL);
    1962 
    1963         /*Clean up and return*/
    1964         xDelete<IssmDouble>(xyz_list);
    1965         xDelete<IssmDouble>(basis);
    1966         xDelete<IssmDouble>(ge);
    1967         xDelete<int>(vertexpidlist);
    1968         delete gauss;
    1969         if(domaintype!=Domain2DhorizontalEnum){basalelement->DeleteMaterials(); delete basalelement;};
    1970 }/*}}}*/
    1971 void AdjointHorizAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
     1971void           AdjointHorizAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
    19721972        int approximation;
    19731973        element->GetInputValue(&approximation,ApproximationEnum);
     
    19791979        }
    19801980}/*}}}*/
    1981 void AdjointHorizAnalysis::InputUpdateFromSolutionHoriz(IssmDouble* solution,Element* element){/*{{{*/
     1981void           AdjointHorizAnalysis::InputUpdateFromSolutionFS(IssmDouble* solution,Element* element){/*{{{*/
     1982        int          i,fe_FS;
     1983        int*         vdoflist=NULL;
     1984        int*         pdoflist=NULL;
     1985        IssmDouble   FSreconditioning;
     1986
     1987        int      domaintype,dim;
     1988        element->FindParam(&domaintype,DomainTypeEnum);
     1989        switch(domaintype){
     1990                case Domain2DhorizontalEnum:
     1991                        dim          = 3;
     1992                        break;
     1993                case Domain2DverticalEnum:
     1994                        dim          = 2;
     1995                        break;
     1996                case Domain3DEnum:
     1997                        dim          = 3;
     1998                        break;
     1999                default: _error_("mesh "<<EnumToStringx(domaintype)<<" not supported yet");
     2000        }
     2001
     2002
     2003        /*Fetch number of nodes and dof for this finite element*/
     2004        int vnumnodes = element->NumberofNodesVelocity();
     2005        int pnumnodes = element->NumberofNodesPressure();
     2006        int vnumdof   = vnumnodes*dim;
     2007        int pnumdof   = pnumnodes*1;
     2008
     2009        /*Initialize values*/
     2010        IssmDouble* values  = xNew<IssmDouble>(vnumdof+pnumdof);
     2011        IssmDouble* lambdax = xNew<IssmDouble>(vnumnodes);
     2012        IssmDouble* lambday = xNew<IssmDouble>(vnumnodes);
     2013        IssmDouble* lambdaz = xNew<IssmDouble>(vnumnodes);
     2014        IssmDouble* lambdap = xNew<IssmDouble>(pnumnodes);
     2015
     2016        int* cs_list = xNew<int>(vnumnodes+pnumnodes);
     2017        if(dim==2) for(i=0;i<vnumnodes;i++) cs_list[i] = XYEnum;
     2018        else       for(i=0;i<vnumnodes;i++) cs_list[i] = XYZEnum;
     2019        for(i=0;i<pnumnodes;i++) cs_list[vnumnodes+i] = PressureEnum;
     2020
     2021        /*Get dof list: */
     2022        element->GetDofListVelocity(&vdoflist,GsetEnum);
     2023        element->GetDofListPressure(&pdoflist,GsetEnum);
     2024
     2025        /*Use the dof list to index into the solution vector: */
     2026        for(i=0;i<vnumdof;i++) values[i]        =solution[vdoflist[i]];
     2027        for(i=0;i<pnumdof;i++) values[vnumdof+i]=solution[pdoflist[i]];
     2028
     2029        /*Transform solution in Cartesian Space*/
     2030        element->TransformSolutionCoord(values,cs_list);
     2031
     2032        /*fill in all arrays: */
     2033        for(i=0;i<vnumnodes;i++){
     2034                lambdax[i] = values[i*dim+0]; if(xIsNan<IssmDouble>(lambdax[i])) _error_("NaN found in solution vector");
     2035                lambday[i] = values[i*dim+1]; if(xIsNan<IssmDouble>(lambday[i])) _error_("NaN found in solution vector");
     2036                if(dim==3){
     2037                        lambdaz[i] = values[i*dim+2]; if(xIsNan<IssmDouble>(lambdaz[i])) _error_("NaN found in solution vector");
     2038                }
     2039        }
     2040        for(i=0;i<pnumnodes;i++){
     2041                lambdap[i] = values[vnumdof+i]; if(xIsNan<IssmDouble>(lambdap[i])) _error_("NaN found in solution vector");
     2042        }
     2043
     2044        /*Recondition pressure and compute vel: */
     2045        element->FindParam(&FSreconditioning,StressbalanceFSreconditioningEnum);
     2046        for(i=0;i<pnumnodes;i++) lambdap[i]=lambdap[i]*FSreconditioning;
     2047
     2048        /*Add vx and vy as inputs to the tria element: */
     2049        element->AddInput(AdjointxEnum,lambdax,element->VelocityInterpolation());
     2050        element->AddInput(AdjointyEnum,lambday,element->VelocityInterpolation());
     2051        if(domaintype!=Domain2DverticalEnum) element->AddInput(AdjointzEnum,lambdaz,element->VelocityInterpolation());
     2052
     2053        element->FindParam(&fe_FS,FlowequationFeFSEnum);
     2054        if(fe_FS!=LATaylorHoodEnum && fe_FS!=LACrouzeixRaviartEnum)     
     2055         element->AddInput(AdjointpEnum,lambdap,element->PressureInterpolation());     
     2056
     2057        /*Free ressources:*/
     2058        xDelete<int>(vdoflist);
     2059        xDelete<int>(pdoflist);
     2060        xDelete<int>(cs_list);
     2061        xDelete<IssmDouble>(lambdap);
     2062        xDelete<IssmDouble>(lambdaz);
     2063        xDelete<IssmDouble>(lambday);
     2064        xDelete<IssmDouble>(lambdax);
     2065        xDelete<IssmDouble>(values);
     2066}/*}}}*/
     2067void           AdjointHorizAnalysis::InputUpdateFromSolutionHoriz(IssmDouble* solution,Element* element){/*{{{*/
    19822068        int  i;
    19832069        int* doflist=NULL;
     
    20252111        xDelete<int>(doflist);
    20262112}/*}}}*/
    2027 void AdjointHorizAnalysis::InputUpdateFromSolutionFS(IssmDouble* solution,Element* element){/*{{{*/
    2028         int          i,fe_FS;
    2029         int*         vdoflist=NULL;
    2030         int*         pdoflist=NULL;
    2031         IssmDouble   FSreconditioning;
    2032 
    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 
    2048 
    2049         /*Fetch number of nodes and dof for this finite element*/
    2050         int vnumnodes = element->NumberofNodesVelocity();
    2051         int pnumnodes = element->NumberofNodesPressure();
    2052         int vnumdof   = vnumnodes*dim;
    2053         int pnumdof   = pnumnodes*1;
    2054 
    2055         /*Initialize values*/
    2056         IssmDouble* values  = xNew<IssmDouble>(vnumdof+pnumdof);
    2057         IssmDouble* lambdax = xNew<IssmDouble>(vnumnodes);
    2058         IssmDouble* lambday = xNew<IssmDouble>(vnumnodes);
    2059         IssmDouble* lambdaz = xNew<IssmDouble>(vnumnodes);
    2060         IssmDouble* lambdap = xNew<IssmDouble>(pnumnodes);
    2061 
    2062         int* cs_list = xNew<int>(vnumnodes+pnumnodes);
    2063         if(dim==2) for(i=0;i<vnumnodes;i++) cs_list[i] = XYEnum;
    2064         else       for(i=0;i<vnumnodes;i++) cs_list[i] = XYZEnum;
    2065         for(i=0;i<pnumnodes;i++) cs_list[vnumnodes+i] = PressureEnum;
    2066 
    2067         /*Get dof list: */
    2068         element->GetDofListVelocity(&vdoflist,GsetEnum);
    2069         element->GetDofListPressure(&pdoflist,GsetEnum);
    2070 
    2071         /*Use the dof list to index into the solution vector: */
    2072         for(i=0;i<vnumdof;i++) values[i]        =solution[vdoflist[i]];
    2073         for(i=0;i<pnumdof;i++) values[vnumdof+i]=solution[pdoflist[i]];
    2074 
    2075         /*Transform solution in Cartesian Space*/
    2076         element->TransformSolutionCoord(values,cs_list);
    2077 
    2078         /*fill in all arrays: */
    2079         for(i=0;i<vnumnodes;i++){
    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                 }
    2085         }
    2086         for(i=0;i<pnumnodes;i++){
    2087                 lambdap[i] = values[vnumdof+i]; if(xIsNan<IssmDouble>(lambdap[i])) _error_("NaN found in solution vector");
    2088         }
    2089 
    2090         /*Recondition pressure and compute vel: */
    2091         element->FindParam(&FSreconditioning,StressbalanceFSreconditioningEnum);
    2092         for(i=0;i<pnumnodes;i++) lambdap[i]=lambdap[i]*FSreconditioning;
    2093 
    2094         /*Add vx and vy as inputs to the tria element: */
    2095         element->AddInput(AdjointxEnum,lambdax,element->VelocityInterpolation());
    2096         element->AddInput(AdjointyEnum,lambday,element->VelocityInterpolation());
    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());     
    2102 
    2103         /*Free ressources:*/
    2104         xDelete<int>(vdoflist);
    2105         xDelete<int>(pdoflist);
    2106         xDelete<int>(cs_list);
    2107         xDelete<IssmDouble>(lambdap);
    2108         xDelete<IssmDouble>(lambdaz);
    2109         xDelete<IssmDouble>(lambday);
    2110         xDelete<IssmDouble>(lambdax);
    2111         xDelete<IssmDouble>(values);
    2112 }/*}}}*/
    2113 void AdjointHorizAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
     2113void           AdjointHorizAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
    21142114        /*Default, do nothing*/
    21152115        return;
  • issm/trunk-jpl/src/c/analyses/AdjointHorizAnalysis.h

    r18835 r18930  
    1313        public:
    1414                /*Model processing*/
    15                 int  DofsPerNode(int** doflist,int domaintype,int approximation);
    16                 void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);
    17                 void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);
    18                 void CreateNodes(Nodes* nodes,IoModel* iomodel);
    1915                void CreateConstraints(Constraints* constraints,IoModel* iomodel);
    2016                void CreateLoads(Loads* loads, IoModel* iomodel);
     17                void CreateNodes(Nodes* nodes,IoModel* iomodel);
     18                int  DofsPerNode(int** doflist,int domaintype,int approximation);
     19                void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);
     20                void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);
    2121
    2222                /*Finite element Analysis*/
     
    2525                ElementMatrix* CreateJacobianMatrix(Element* element);
    2626                ElementMatrix* CreateKMatrix(Element* element);
     27                ElementMatrix* CreateKMatrixFS(Element* element);
     28                ElementMatrix* CreateKMatrixHO(Element* element);
     29                ElementMatrix* CreateKMatrixL1L2(Element* element);
    2730                ElementMatrix* CreateKMatrixSSA(Element* element);
    28                 ElementMatrix* CreateKMatrixL1L2(Element* element);
    29                 ElementMatrix* CreateKMatrixHO(Element* element);
    30                 ElementMatrix* CreateKMatrixFS(Element* element);
    3131                ElementVector* CreatePVector(Element* element);
    32                 ElementVector* CreatePVectorSSA(Element* element);
     32                ElementVector* CreatePVectorFS(Element* element);
    3333                ElementVector* CreatePVectorL1L2(Element* element);
    3434                ElementVector* CreatePVectorHO(Element* element);
    35                 ElementVector* CreatePVectorFS(Element* element);
    36                 void GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);
    37                 void GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);
    38                 void GradientJDragGradient(Element* element,Vector<IssmDouble>* gradient,int control_index);
    39                 void GradientJBbarGradient(Element* element,Vector<IssmDouble>* gradient,int control_index);
    40                 void GradientJBGradient(Element* element,Vector<IssmDouble>* gradient,int control_index);
    41                 void GradientJDragSSA(Element* element,Vector<IssmDouble>* gradient,int control_index);
    42                 void GradientJDragL1L2(Element* element,Vector<IssmDouble>* gradient,int control_index);
    43                 void GradientJDragHO(Element* element,Vector<IssmDouble>* gradient,int control_index);
    44                 void GradientJDragFS(Element* element,Vector<IssmDouble>* gradient,int control_index);
    45                 void GradientJBbarSSA(Element* element,Vector<IssmDouble>* gradient,int control_index);
    46                 void GradientJBbarL1L2(Element* element,Vector<IssmDouble>* gradient,int control_index);
    47                 void GradientJBbarHO(Element* element,Vector<IssmDouble>* gradient,int control_index);
    48                 void GradientJBbarFS(Element* element,Vector<IssmDouble>* gradient,int control_index);
    49                 void GradientJBSSA(Element* element,Vector<IssmDouble>* gradient,int control_index);
    50                 void GradientJBHO(Element* element,Vector<IssmDouble>* gradient,int control_index);
    51                 void GradientJBFS(Element* element,Vector<IssmDouble>* gradient,int control_index);
    52                 void GradientJDSSA(Element* element,Vector<IssmDouble>* gradient,int control_index);
    53                 void InputUpdateFromSolution(IssmDouble* solution,Element* element);
    54                 void UpdateConstraints(FemModel* femmodel);
    55                 void InputUpdateFromSolutionHoriz(IssmDouble* solution,Element* element);
    56                 void InputUpdateFromSolutionFS(IssmDouble* solution,Element* element);
     35                ElementVector* CreatePVectorSSA(Element* element);
     36                void           GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);
     37                void           GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);
     38                void           GradientJBbarFS(Element* element,Vector<IssmDouble>* gradient,int control_index);
     39                void           GradientJBbarGradient(Element* element,Vector<IssmDouble>* gradient,int control_index);
     40                void           GradientJBbarL1L2(Element* element,Vector<IssmDouble>* gradient,int control_index);
     41                void           GradientJBbarHO(Element* element,Vector<IssmDouble>* gradient,int control_index);
     42                void           GradientJBbarSSA(Element* element,Vector<IssmDouble>* gradient,int control_index);
     43                void           GradientJBFS(Element* element,Vector<IssmDouble>* gradient,int control_index);
     44                void           GradientJBGradient(Element* element,Vector<IssmDouble>* gradient,int control_index);
     45                void           GradientJBHO(Element* element,Vector<IssmDouble>* gradient,int control_index);
     46                void           GradientJBSSA(Element* element,Vector<IssmDouble>* gradient,int control_index);
     47                void           GradientJDragFS(Element* element,Vector<IssmDouble>* gradient,int control_index);
     48                void           GradientJDragGradient(Element* element,Vector<IssmDouble>* gradient,int control_index);
     49                void           GradientJDragL1L2(Element* element,Vector<IssmDouble>* gradient,int control_index);
     50                void           GradientJDragHO(Element* element,Vector<IssmDouble>* gradient,int control_index);
     51                void           GradientJDragSSA(Element* element,Vector<IssmDouble>* gradient,int control_index);
     52                void           GradientJDSSA(Element* element,Vector<IssmDouble>* gradient,int control_index);
     53                void           InputUpdateFromSolution(IssmDouble* solution,Element* element);
     54                void           InputUpdateFromSolutionFS(IssmDouble* solution,Element* element);
     55                void           InputUpdateFromSolutionHoriz(IssmDouble* solution,Element* element);
     56                void           UpdateConstraints(FemModel* femmodel);
    5757};
    5858#endif
  • issm/trunk-jpl/src/c/analyses/Balancethickness2Analysis.cpp

    r18715 r18930  
    66
    77/*Model processing*/
     8void Balancethickness2Analysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
     9
     10
     11        int finiteelement = P1Enum;
     12        IoModelToConstraintsx(constraints,iomodel,BalancethicknessSpcthicknessEnum,Balancethickness2AnalysisEnum,finiteelement);
     13
     14}/*}}}*/
     15void Balancethickness2Analysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
     16
     17}/*}}}*/
     18void Balancethickness2Analysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
     19
     20        int finiteelement = P1Enum;
     21        ::CreateNodes(nodes,iomodel,Balancethickness2AnalysisEnum,finiteelement);
     22}/*}}}*/
    823int  Balancethickness2Analysis::DofsPerNode(int** doflist,int domaintype,int approximation){/*{{{*/
    924        return 1;
    10 }/*}}}*/
    11 void Balancethickness2Analysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
    1225}/*}}}*/
    1326void Balancethickness2Analysis::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/
     
    3851
    3952}/*}}}*/
    40 void Balancethickness2Analysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
    41 
    42         int finiteelement = P1Enum;
    43         ::CreateNodes(nodes,iomodel,Balancethickness2AnalysisEnum,finiteelement);
    44 }/*}}}*/
    45 void Balancethickness2Analysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
    46 
    47 
    48         int finiteelement = P1Enum;
    49         IoModelToConstraintsx(constraints,iomodel,BalancethicknessSpcthicknessEnum,Balancethickness2AnalysisEnum,finiteelement);
    50 
    51 }/*}}}*/
    52 void Balancethickness2Analysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
    53 
     53void Balancethickness2Analysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
    5454}/*}}}*/
    5555
     
    6262        return NULL;
    6363}/*}}}*/
    64 ElementMatrix* Balancethickness2Analysis::CreateJacobianMatrix(Element* element){/*{{{*/
    65 _error_("Not implemented");
    66 }/*}}}*/
    67 ElementMatrix* Balancethickness2Analysis::CreateKMatrix(Element* element){/*{{{*/
    68 
    69         /*Intermediaries */
    70         IssmDouble  Jdet,D0,omega;
    71         IssmDouble* xyz_list = NULL;
    72 
    73         /*Fetch number of nodes and dof for this finite element*/
    74         int numnodes = element->GetNumberOfNodes();
    75 
    76         /*Initialize Element vector and other vectors*/
    77         ElementMatrix* Ke     = element->NewElementMatrix();
    78         IssmDouble*    dbasis = xNew<IssmDouble>(2*numnodes);
    79 
    80         /*Retrieve all inputs and parameters*/
    81         element->GetVerticesCoordinates(&xyz_list);
    82         Input* omega_input = element->GetInput(BalancethicknessOmegaEnum); _assert_(omega_input);
    83         Input* D0_input    = element->GetInput(BalancethicknessD0Enum);
    84         if(!D0_input){
    85                 this->CreateD0(element);
    86                 D0_input = element->GetInput(BalancethicknessD0Enum); _assert_(D0_input);
    87         }
    88 
    89         /* Start  looping on the number of gaussian points: */
    90         Gauss* gauss=element->NewGauss(2);
    91         for(int ig=gauss->begin();ig<gauss->end();ig++){
    92                 gauss->GaussPoint(ig);
    93                 element->NodalFunctionsDerivatives(dbasis,xyz_list,gauss);
    94                 element->JacobianDeterminant(&Jdet,xyz_list,gauss);
    95                 D0_input->GetInputValue(&D0,gauss);
    96                 omega_input->GetInputValue(&omega,gauss);
    97 
    98                 for(int i=0;i<numnodes;i++){
    99                         for(int j=0;j<numnodes;j++){
    100                                 Ke->values[i*numnodes+j] += D0*exp(omega)*gauss->weight*Jdet*(dbasis[0*numnodes+i]*dbasis[0*numnodes+j] + dbasis[1*numnodes+i]*dbasis[1*numnodes+j]);
    101                         }
    102                 }
    103         }
    104 
    105         /*Clean up and return*/
    106         xDelete<IssmDouble>(xyz_list);
    107         xDelete<IssmDouble>(dbasis);
    108         delete gauss;
    109         return Ke;
    110 }/*}}}*/
    111 ElementVector* Balancethickness2Analysis::CreatePVector(Element* element){/*{{{*/
    112 
    113         /*Intermediaries */
    114         IssmDouble  dhdt,mb,ms,Jdet;
    115         IssmDouble* xyz_list = NULL;
    116 
    117         /*Fetch number of nodes and dof for this finite element*/
    118         int numnodes = element->GetNumberOfNodes();
    119 
    120         /*Initialize Element vector and other vectors*/
    121         ElementVector* pe    = element->NewElementVector();
    122         IssmDouble*    basis = xNew<IssmDouble>(numnodes);
    123 
    124         /*Retrieve all inputs and parameters*/
    125         element->GetVerticesCoordinates(&xyz_list);
    126         Input* ms_input   = element->GetInput(SurfaceforcingsMassBalanceEnum);                _assert_(ms_input);
    127         Input* mb_input   = element->GetInput(BasalforcingsGroundediceMeltingRateEnum);       _assert_(mb_input);
    128         Input* dhdt_input = element->GetInput(BalancethicknessThickeningRateEnum);            _assert_(dhdt_input);
    129 
    130         /* Start  looping on the number of gaussian points: */
    131         Gauss* gauss=element->NewGauss(2);
    132         for(int ig=gauss->begin();ig<gauss->end();ig++){
    133                 gauss->GaussPoint(ig);
    134 
    135                 element->JacobianDeterminant(&Jdet,xyz_list,gauss);
    136                 element->NodalFunctions(basis,gauss);
    137 
    138                 ms_input->GetInputValue(&ms,gauss);
    139                 mb_input->GetInputValue(&mb,gauss);
    140                 dhdt_input->GetInputValue(&dhdt,gauss);
    141 
    142                 for(int i=0;i<numnodes;i++) pe->values[i]+=Jdet*gauss->weight*(
    143                                         (ms-mb-dhdt)*basis[i]
    144                                         );
    145         }
    146 
    147         /*Clean up and return*/
    148         xDelete<IssmDouble>(xyz_list);
    149         xDelete<IssmDouble>(basis);
    150         delete gauss;
    151         return pe;
    152 }/*}}}*/
    153 void Balancethickness2Analysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
    154                 element->GetSolutionFromInputsOneDof(solution,SurfaceEnum);
    155 }/*}}}*/
    156 void Balancethickness2Analysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
    157         _error_("Not implemented yet");
    158 }/*}}}*/
    159 void Balancethickness2Analysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
    160 
    161         /*Intermediaries*/
    162         IssmDouble  ds[2],s,b,D;
    163         IssmDouble* xyz_list = NULL;
    164 
    165         //element->InputUpdateFromSolutionOneDof(solution,ThicknessEnum);
    166         element->InputUpdateFromSolutionOneDof(solution,SurfaceEnum);
    167 
    168         /*Fetch number of vertices and allocate velocity vectors*/
    169         int numvertices = element->GetNumberOfVertices();
    170         IssmDouble* vel_list = xNew<IssmDouble>(numvertices);
    171         IssmDouble* vx_list  = xNew<IssmDouble>(numvertices);
    172         IssmDouble* vy_list  = xNew<IssmDouble>(numvertices);
    173 
    174         /*Retrieve all inputs and parameters*/
    175         element->GetVerticesCoordinates(&xyz_list);
    176         Input* D_input   = element->GetInput(BalancethicknessDiffusionCoefficientEnum);
    177         Input* H_input   = element->GetInput(ThicknessEnum);                            _assert_(H_input);
    178         Input* s_input   = element->GetInput(SurfaceEnum);                              _assert_(s_input);
    179         Input* b_input   = element->GetInput(BaseEnum);                                 _assert_(b_input);
    180 
    181         /*Calculate velocities*/
    182         Gauss* gauss=element->NewGauss();
    183         for(int iv=0;iv<numvertices;iv++){
    184                 gauss->GaussVertex(iv);
    185 
    186                 if(D_input){
    187                         D_input->GetInputValue(&D,gauss);
    188                 }
    189                 else{
    190                         D = 0.;
    191                 }
    192                 b_input->GetInputValue(&b,gauss);
    193                 s_input->GetInputValue(&s,gauss);
    194                 s_input->GetInputDerivativeValue(&ds[0],xyz_list,gauss);
    195 
    196                 vx_list[iv] = -1./(s-b)*D*ds[0];
    197                 vy_list[iv] = -1./(s-b)*D*ds[1];
    198                 vel_list[iv] = sqrt(pow(vx_list[iv],2) + pow(vy_list[iv],2));
    199         }
    200 
    201         /*Add vx and vy as inputs to the tria element: */
    202         element->AddInput(VxEnum,vx_list,P1Enum);
    203         element->AddInput(VyEnum,vy_list,P1Enum);
    204         element->AddInput(VelEnum,vel_list,P1Enum);
    205 
    206         /*Free ressources:*/
    207         delete gauss;
    208         xDelete<IssmDouble>(vy_list);
    209         xDelete<IssmDouble>(vx_list);
    210         xDelete<IssmDouble>(vel_list);
    211         xDelete<IssmDouble>(xyz_list);
    212 }/*}}}*/
    213 void Balancethickness2Analysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
    214         /*Default, do nothing*/
    215         return;
    216 }/*}}}*/
    217 
    218 /*Specifics*/
    219 void Balancethickness2Analysis::CreateD0(Element* element){/*{{{*/
     64void           Balancethickness2Analysis::CreateD0(Element* element){/*{{{*/
    22065
    22166        /*Intermediaries */
     
    281126        delete gauss;
    282127}/*}}}*/
     128ElementMatrix* Balancethickness2Analysis::CreateJacobianMatrix(Element* element){/*{{{*/
     129_error_("Not implemented");
     130}/*}}}*/
     131ElementMatrix* Balancethickness2Analysis::CreateKMatrix(Element* element){/*{{{*/
     132
     133        /*Intermediaries */
     134        IssmDouble  Jdet,D0,omega;
     135        IssmDouble* xyz_list = NULL;
     136
     137        /*Fetch number of nodes and dof for this finite element*/
     138        int numnodes = element->GetNumberOfNodes();
     139
     140        /*Initialize Element vector and other vectors*/
     141        ElementMatrix* Ke     = element->NewElementMatrix();
     142        IssmDouble*    dbasis = xNew<IssmDouble>(2*numnodes);
     143
     144        /*Retrieve all inputs and parameters*/
     145        element->GetVerticesCoordinates(&xyz_list);
     146        Input* omega_input = element->GetInput(BalancethicknessOmegaEnum); _assert_(omega_input);
     147        Input* D0_input    = element->GetInput(BalancethicknessD0Enum);
     148        if(!D0_input){
     149                this->CreateD0(element);
     150                D0_input = element->GetInput(BalancethicknessD0Enum); _assert_(D0_input);
     151        }
     152
     153        /* Start  looping on the number of gaussian points: */
     154        Gauss* gauss=element->NewGauss(2);
     155        for(int ig=gauss->begin();ig<gauss->end();ig++){
     156                gauss->GaussPoint(ig);
     157                element->NodalFunctionsDerivatives(dbasis,xyz_list,gauss);
     158                element->JacobianDeterminant(&Jdet,xyz_list,gauss);
     159                D0_input->GetInputValue(&D0,gauss);
     160                omega_input->GetInputValue(&omega,gauss);
     161
     162                for(int i=0;i<numnodes;i++){
     163                        for(int j=0;j<numnodes;j++){
     164                                Ke->values[i*numnodes+j] += D0*exp(omega)*gauss->weight*Jdet*(dbasis[0*numnodes+i]*dbasis[0*numnodes+j] + dbasis[1*numnodes+i]*dbasis[1*numnodes+j]);
     165                        }
     166                }
     167        }
     168
     169        /*Clean up and return*/
     170        xDelete<IssmDouble>(xyz_list);
     171        xDelete<IssmDouble>(dbasis);
     172        delete gauss;
     173        return Ke;
     174}/*}}}*/
     175ElementVector* Balancethickness2Analysis::CreatePVector(Element* element){/*{{{*/
     176
     177        /*Intermediaries */
     178        IssmDouble  dhdt,mb,ms,Jdet;
     179        IssmDouble* xyz_list = NULL;
     180
     181        /*Fetch number of nodes and dof for this finite element*/
     182        int numnodes = element->GetNumberOfNodes();
     183
     184        /*Initialize Element vector and other vectors*/
     185        ElementVector* pe    = element->NewElementVector();
     186        IssmDouble*    basis = xNew<IssmDouble>(numnodes);
     187
     188        /*Retrieve all inputs and parameters*/
     189        element->GetVerticesCoordinates(&xyz_list);
     190        Input* ms_input   = element->GetInput(SurfaceforcingsMassBalanceEnum);                _assert_(ms_input);
     191        Input* mb_input   = element->GetInput(BasalforcingsGroundediceMeltingRateEnum);       _assert_(mb_input);
     192        Input* dhdt_input = element->GetInput(BalancethicknessThickeningRateEnum);            _assert_(dhdt_input);
     193
     194        /* Start  looping on the number of gaussian points: */
     195        Gauss* gauss=element->NewGauss(2);
     196        for(int ig=gauss->begin();ig<gauss->end();ig++){
     197                gauss->GaussPoint(ig);
     198
     199                element->JacobianDeterminant(&Jdet,xyz_list,gauss);
     200                element->NodalFunctions(basis,gauss);
     201
     202                ms_input->GetInputValue(&ms,gauss);
     203                mb_input->GetInputValue(&mb,gauss);
     204                dhdt_input->GetInputValue(&dhdt,gauss);
     205
     206                for(int i=0;i<numnodes;i++) pe->values[i]+=Jdet*gauss->weight*(
     207                                        (ms-mb-dhdt)*basis[i]
     208                                        );
     209        }
     210
     211        /*Clean up and return*/
     212        xDelete<IssmDouble>(xyz_list);
     213        xDelete<IssmDouble>(basis);
     214        delete gauss;
     215        return pe;
     216}/*}}}*/
     217void           Balancethickness2Analysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
     218                element->GetSolutionFromInputsOneDof(solution,SurfaceEnum);
     219}/*}}}*/
     220void           Balancethickness2Analysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
     221        _error_("Not implemented yet");
     222}/*}}}*/
     223void           Balancethickness2Analysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
     224
     225        /*Intermediaries*/
     226        IssmDouble  ds[2],s,b,D;
     227        IssmDouble* xyz_list = NULL;
     228
     229        //element->InputUpdateFromSolutionOneDof(solution,ThicknessEnum);
     230        element->InputUpdateFromSolutionOneDof(solution,SurfaceEnum);
     231
     232        /*Fetch number of vertices and allocate velocity vectors*/
     233        int numvertices = element->GetNumberOfVertices();
     234        IssmDouble* vel_list = xNew<IssmDouble>(numvertices);
     235        IssmDouble* vx_list  = xNew<IssmDouble>(numvertices);
     236        IssmDouble* vy_list  = xNew<IssmDouble>(numvertices);
     237
     238        /*Retrieve all inputs and parameters*/
     239        element->GetVerticesCoordinates(&xyz_list);
     240        Input* D_input   = element->GetInput(BalancethicknessDiffusionCoefficientEnum);
     241        Input* H_input   = element->GetInput(ThicknessEnum);                            _assert_(H_input);
     242        Input* s_input   = element->GetInput(SurfaceEnum);                              _assert_(s_input);
     243        Input* b_input   = element->GetInput(BaseEnum);                                 _assert_(b_input);
     244
     245        /*Calculate velocities*/
     246        Gauss* gauss=element->NewGauss();
     247        for(int iv=0;iv<numvertices;iv++){
     248                gauss->GaussVertex(iv);
     249
     250                if(D_input){
     251                        D_input->GetInputValue(&D,gauss);
     252                }
     253                else{
     254                        D = 0.;
     255                }
     256                b_input->GetInputValue(&b,gauss);
     257                s_input->GetInputValue(&s,gauss);
     258                s_input->GetInputDerivativeValue(&ds[0],xyz_list,gauss);
     259
     260                vx_list[iv] = -1./(s-b)*D*ds[0];
     261                vy_list[iv] = -1./(s-b)*D*ds[1];
     262                vel_list[iv] = sqrt(pow(vx_list[iv],2) + pow(vy_list[iv],2));
     263        }
     264
     265        /*Add vx and vy as inputs to the tria element: */
     266        element->AddInput(VxEnum,vx_list,P1Enum);
     267        element->AddInput(VyEnum,vy_list,P1Enum);
     268        element->AddInput(VelEnum,vel_list,P1Enum);
     269
     270        /*Free ressources:*/
     271        delete gauss;
     272        xDelete<IssmDouble>(vy_list);
     273        xDelete<IssmDouble>(vx_list);
     274        xDelete<IssmDouble>(vel_list);
     275        xDelete<IssmDouble>(xyz_list);
     276}/*}}}*/
     277void           Balancethickness2Analysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
     278        /*Default, do nothing*/
     279        return;
     280}/*}}}*/
  • issm/trunk-jpl/src/c/analyses/Balancethickness2Analysis.h

    r18565 r18930  
    1313        public:
    1414                /*Model processing*/
    15                 int  DofsPerNode(int** doflist,int domaintype,int approximation);
    16                 void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);
    17                 void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);
    18                 void CreateNodes(Nodes* nodes,IoModel* iomodel);
    1915                void CreateConstraints(Constraints* constraints,IoModel* iomodel);
    2016                void CreateLoads(Loads* loads, IoModel* iomodel);
     17                void CreateNodes(Nodes* nodes,IoModel* iomodel);
     18                int  DofsPerNode(int** doflist,int domaintype,int approximation);
     19                void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);
     20                void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);
    2121
    2222                /*Finite element Analysis*/
    2323                void           Core(FemModel* femmodel);
    2424                ElementVector* CreateDVector(Element* element);
     25                void           CreateD0(Element* element);
    2526                ElementMatrix* CreateJacobianMatrix(Element* element);
    2627                ElementMatrix* CreateKMatrix(Element* element);
    2728                ElementVector* CreatePVector(Element* element);
    28                 void GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);
    29                 void GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);
    30                 void InputUpdateFromSolution(IssmDouble* solution,Element* element);
    31                 void UpdateConstraints(FemModel* femmodel);
    32 
    33                 /*Specifics*/
    34                 void CreateD0(Element* element);
     29                void           GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);
     30                void           GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);
     31                void           InputUpdateFromSolution(IssmDouble* solution,Element* element);
     32                void           UpdateConstraints(FemModel* femmodel);
    3533};
    3634#endif
  • issm/trunk-jpl/src/c/analyses/BalancethicknessAnalysis.cpp

    r18068 r18930  
    66
    77/*Model processing*/
     8void BalancethicknessAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
     9
     10        /*Fetch parameters: */
     11        int    stabilization;   
     12        iomodel->Constant(&stabilization,BalancethicknessStabilizationEnum);
     13
     14        /*Do not add constraints in DG*/
     15        if(stabilization!=3){
     16                IoModelToConstraintsx(constraints,iomodel,BalancethicknessSpcthicknessEnum,BalancethicknessAnalysisEnum,P1Enum);
     17        }
     18
     19}/*}}}*/
     20void BalancethicknessAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
     21
     22        /*Intermediary*/
     23        int element;
     24        int stabilization;
     25
     26        /*Fetch parameters: */
     27        iomodel->Constant(&stabilization,BalancethicknessStabilizationEnum);
     28
     29        /*Loads only in DG*/
     30        if (stabilization==3){
     31
     32                /*Get faces and elements*/
     33                CreateFaces(iomodel);
     34                iomodel->FetchData(1,ThicknessEnum);
     35
     36                /*First load data:*/
     37                for(int i=0;i<iomodel->numberoffaces;i++){
     38
     39                        /*Get left and right elements*/
     40                        element=iomodel->faces[4*i+2]-1; //faces are [node1 node2 elem1 elem2]
     41
     42                        /*Now, if this element is not in the partition, pass: */
     43                        if(!iomodel->my_elements[element]) continue;
     44
     45                        /* Add load */
     46                        loads->AddObject(new Numericalflux(iomodel->loadcounter+i+1,i,i,iomodel,BalancethicknessAnalysisEnum));
     47                }
     48
     49                /*Free data: */
     50                iomodel->DeleteData(1,ThicknessEnum);
     51        }
     52}/*}}}*/
     53void BalancethicknessAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
     54
     55        int  stabilization;
     56        iomodel->Constant(&stabilization,BalancethicknessStabilizationEnum);
     57
     58        /*Check in 3d*/
     59        if(stabilization==3 && iomodel->domaintype==Domain3DEnum) _error_("DG 3d not implemented yet");
     60
     61        /*First fetch data: */
     62        if(iomodel->domaintype==Domain3DEnum) iomodel->FetchData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum);
     63        if(stabilization!=3){
     64                ::CreateNodes(nodes,iomodel,BalancethicknessAnalysisEnum,P1Enum);
     65        }
     66        else{
     67                ::CreateNodes(nodes,iomodel,BalancethicknessAnalysisEnum,P1DGEnum);
     68        }
     69        iomodel->DeleteData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum);
     70}/*}}}*/
    871int  BalancethicknessAnalysis::DofsPerNode(int** doflist,int domaintype,int approximation){/*{{{*/
    972        return 1;
    10 }/*}}}*/
    11 void BalancethicknessAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
    12         parameters->AddObject(iomodel->CopyConstantObject(BalancethicknessStabilizationEnum));
    1373}/*}}}*/
    1474void BalancethicknessAnalysis::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/
     
    50110        }
    51111}/*}}}*/
    52 void BalancethicknessAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
    53 
    54         int  stabilization;
    55         iomodel->Constant(&stabilization,BalancethicknessStabilizationEnum);
    56 
    57         /*Check in 3d*/
    58         if(stabilization==3 && iomodel->domaintype==Domain3DEnum) _error_("DG 3d not implemented yet");
    59 
    60         /*First fetch data: */
    61         if(iomodel->domaintype==Domain3DEnum) iomodel->FetchData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum);
    62         if(stabilization!=3){
    63                 ::CreateNodes(nodes,iomodel,BalancethicknessAnalysisEnum,P1Enum);
    64         }
    65         else{
    66                 ::CreateNodes(nodes,iomodel,BalancethicknessAnalysisEnum,P1DGEnum);
    67         }
    68         iomodel->DeleteData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum);
    69 }/*}}}*/
    70 void BalancethicknessAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
    71 
    72         /*Fetch parameters: */
    73         int    stabilization;   
    74         iomodel->Constant(&stabilization,BalancethicknessStabilizationEnum);
    75 
    76         /*Do not add constraints in DG*/
    77         if(stabilization!=3){
    78                 IoModelToConstraintsx(constraints,iomodel,BalancethicknessSpcthicknessEnum,BalancethicknessAnalysisEnum,P1Enum);
    79         }
    80 
    81 }/*}}}*/
    82 void BalancethicknessAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
    83 
    84         /*Intermediary*/
    85         int element;
    86         int stabilization;
    87 
    88         /*Fetch parameters: */
    89         iomodel->Constant(&stabilization,BalancethicknessStabilizationEnum);
    90 
    91         /*Loads only in DG*/
    92         if (stabilization==3){
    93 
    94                 /*Get faces and elements*/
    95                 CreateFaces(iomodel);
    96                 iomodel->FetchData(1,ThicknessEnum);
    97 
    98                 /*First load data:*/
    99                 for(int i=0;i<iomodel->numberoffaces;i++){
    100 
    101                         /*Get left and right elements*/
    102                         element=iomodel->faces[4*i+2]-1; //faces are [node1 node2 elem1 elem2]
    103 
    104                         /*Now, if this element is not in the partition, pass: */
    105                         if(!iomodel->my_elements[element]) continue;
    106 
    107                         /* Add load */
    108                         loads->AddObject(new Numericalflux(iomodel->loadcounter+i+1,i,i,iomodel,BalancethicknessAnalysisEnum));
    109                 }
    110 
    111                 /*Free data: */
    112                 iomodel->DeleteData(1,ThicknessEnum);
    113         }
     112void BalancethicknessAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
     113        parameters->AddObject(iomodel->CopyConstantObject(BalancethicknessStabilizationEnum));
    114114}/*}}}*/
    115115
     
    421421        return pe;
    422422}/*}}}*/
    423 void BalancethicknessAnalysis::GetB(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
     423void           BalancethicknessAnalysis::GetB(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
    424424        /*Compute B  matrix. B=[B1 B2 B3] where Bi is of size 3*NDOF2.
    425425         * For node i, Bi can be expressed in the actual coordinate system
     
    448448        xDelete<IssmDouble>(basis);
    449449}/*}}}*/
    450 void BalancethicknessAnalysis::GetBprime(IssmDouble* Bprime,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
     450void           BalancethicknessAnalysis::GetBprime(IssmDouble* Bprime,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
    451451        /*Compute B'  matrix. B'=[B1' B2' B3'] where Bi' is of size 3*NDOF2.
    452452         * For node i, Bi' can be expressed in the actual coordinate system
     
    476476
    477477}/*}}}*/
    478 void BalancethicknessAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
     478void           BalancethicknessAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
    479479           _error_("not implemented yet");
    480480}/*}}}*/
    481 void BalancethicknessAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
     481void           BalancethicknessAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
    482482        /* WARNING: this gradient is valid for Soft balance thickness only */
    483483
     
    595595
    596596}/*}}}*/
    597 void BalancethicknessAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
     597void           BalancethicknessAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
    598598
    599599        int domaintype;
     
    609609        }
    610610}/*}}}*/
    611 void BalancethicknessAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
     611void           BalancethicknessAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
    612612        /*Default, do nothing*/
    613613        return;
  • issm/trunk-jpl/src/c/analyses/BalancethicknessAnalysis.h

    r18057 r18930  
    1313        public:
    1414                /*Model processing*/
    15                 int  DofsPerNode(int** doflist,int domaintype,int approximation);
    16                 void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);
    17                 void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);
    18                 void CreateNodes(Nodes* nodes,IoModel* iomodel);
    1915                void CreateConstraints(Constraints* constraints,IoModel* iomodel);
    2016                void CreateLoads(Loads* loads, IoModel* iomodel);
     17                void CreateNodes(Nodes* nodes,IoModel* iomodel);
     18                int  DofsPerNode(int** doflist,int domaintype,int approximation);
     19                void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);
     20                void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);
    2121
    2222                /*Finite element Analysis*/
     
    3030                ElementVector* CreatePVectorCG(Element* element);
    3131                ElementVector* CreatePVectorDG(Element* element);
    32                 void GetB(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss);
    33                 void GetBprime(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss);
    34                 void GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);
    35                 void GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);
    36                 void InputUpdateFromSolution(IssmDouble* solution,Element* element);
    37                 void UpdateConstraints(FemModel* femmodel);
     32                void           GetB(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss);
     33                void           GetBprime(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss);
     34                void           GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);
     35                void           GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);
     36                void           InputUpdateFromSolution(IssmDouble* solution,Element* element);
     37                void           UpdateConstraints(FemModel* femmodel);
    3838};
    3939#endif
  • issm/trunk-jpl/src/c/analyses/BalancevelocityAnalysis.cpp

    r18593 r18930  
    66
    77/*Model processing*/
     8void BalancevelocityAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
     9
     10        /*No constraints for now*/
     11        //IoModelToConstraintsx(constraints,iomodel,BalancethicknessSpcthicknessEnum,BalancevelocityAnalysisEnum,P1Enum);
     12}/*}}}*/
     13void BalancevelocityAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
     14
     15        /*No loads*/
     16}/*}}}*/
     17void BalancevelocityAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
     18
     19        /*Check in 3d*/
     20        if(iomodel->domaintype==Domain3DEnum) _error_("DG 3d not implemented yet");
     21
     22        /*First fetch data: */
     23        ::CreateNodes(nodes,iomodel,BalancevelocityAnalysisEnum,P1Enum);
     24}/*}}}*/
    825int  BalancevelocityAnalysis::DofsPerNode(int** doflist,int domaintype,int approximation){/*{{{*/
    926        return 1;
    10 }/*}}}*/
    11 void BalancevelocityAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
    1227}/*}}}*/
    1328void BalancevelocityAnalysis::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/
     
    3853        }
    3954}/*}}}*/
    40 void BalancevelocityAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
    41 
    42         /*Check in 3d*/
    43         if(iomodel->domaintype==Domain3DEnum) _error_("DG 3d not implemented yet");
    44 
    45         /*First fetch data: */
    46         ::CreateNodes(nodes,iomodel,BalancevelocityAnalysisEnum,P1Enum);
    47 }/*}}}*/
    48 void BalancevelocityAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
    49 
    50         /*No constraints for now*/
    51         //IoModelToConstraintsx(constraints,iomodel,BalancethicknessSpcthicknessEnum,BalancevelocityAnalysisEnum,P1Enum);
    52 }/*}}}*/
    53 void BalancevelocityAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
    54 
    55         /*No loads*/
     55void BalancevelocityAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
    5656}/*}}}*/
    5757
     
    238238        return pe;
    239239}/*}}}*/
    240 void BalancevelocityAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
     240void           BalancevelocityAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
    241241           _error_("not implemented yet");
    242242}/*}}}*/
    243 void BalancevelocityAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
     243void           BalancevelocityAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
    244244        _error_("Not implemented yet");
    245245}/*}}}*/
    246 void BalancevelocityAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
     246void           BalancevelocityAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
    247247
    248248        int domaintype;
     
    258258        }
    259259}/*}}}*/
    260 void BalancevelocityAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
     260void           BalancevelocityAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
    261261        /*Default, do nothing*/
    262262        return;
  • issm/trunk-jpl/src/c/analyses/BalancevelocityAnalysis.h

    r18057 r18930  
    1313        public:
    1414                /*Model processing*/
    15                 int  DofsPerNode(int** doflist,int domaintype,int approximation);
    16                 void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);
    17                 void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);
    18                 void CreateNodes(Nodes* nodes,IoModel* iomodel);
    1915                void CreateConstraints(Constraints* constraints,IoModel* iomodel);
    2016                void CreateLoads(Loads* loads, IoModel* iomodel);
     17                void CreateNodes(Nodes* nodes,IoModel* iomodel);
     18                int  DofsPerNode(int** doflist,int domaintype,int approximation);
     19                void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);
     20                void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);
    2121
    2222                /*Finite element Analysis*/
     
    2626                ElementMatrix* CreateKMatrix(Element* element);
    2727                ElementVector* CreatePVector(Element* element);
    28                 void GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);
    29                 void GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);
    30                 void InputUpdateFromSolution(IssmDouble* solution,Element* element);
    31                 void UpdateConstraints(FemModel* femmodel);
     28                void           GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);
     29                void           GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);
     30                void           InputUpdateFromSolution(IssmDouble* solution,Element* element);
     31                void           UpdateConstraints(FemModel* femmodel);
    3232};
    3333#endif
  • issm/trunk-jpl/src/c/analyses/DamageEvolutionAnalysis.cpp

    r18736 r18930  
    66
    77/*Model processing*/
     8void DamageEvolutionAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
     9
     10        int finiteelement;
     11        iomodel->Constant(&finiteelement,DamageElementinterpEnum);
     12
     13        IoModelToConstraintsx(constraints,iomodel,DamageSpcdamageEnum,DamageEvolutionAnalysisEnum,finiteelement);
     14
     15}/*}}}*/
     16void DamageEvolutionAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
     17
     18        /*Nothing for now*/
     19
     20}/*}}}*/
     21void DamageEvolutionAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
     22
     23        int finiteelement;
     24
     25        iomodel->Constant(&finiteelement,DamageElementinterpEnum);
     26        ::CreateNodes(nodes,iomodel,DamageEvolutionAnalysisEnum,finiteelement);
     27}/*}}}*/
    828int  DamageEvolutionAnalysis::DofsPerNode(int** doflist,int domaintype,int approximation){/*{{{*/
    929        return 1;
     30}/*}}}*/
     31void DamageEvolutionAnalysis::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/
     32
     33        int finiteelement;
     34        bool   islevelset;
     35
     36        iomodel->Constant(&finiteelement,DamageElementinterpEnum);
     37        iomodel->Constant(&islevelset,TransientIslevelsetEnum);
     38
     39        /*Update elements: */
     40        int counter=0;
     41        for(int i=0;i<iomodel->numberofelements;i++){
     42                if(iomodel->my_elements[i]){
     43                        Element* element=(Element*)elements->GetObjectByOffset(counter);
     44                        element->Update(i,iomodel,analysis_counter,analysis_type,finiteelement);
     45                        counter++;
     46                }
     47        }
     48
     49        /*What input do I need to run my damage evolution model?*/
     50        iomodel->FetchDataToInput(elements,VxEnum);
     51        iomodel->FetchDataToInput(elements,VyEnum);
     52        if(iomodel->domaintype==Domain3DEnum) iomodel->FetchDataToInput(elements,VzEnum);
     53        iomodel->FetchDataToInput(elements,DamageDEnum);
     54        iomodel->FetchDataToInput(elements,MaskIceLevelsetEnum);
     55        iomodel->FetchDataToInput(elements,PressureEnum);
     56
     57        if(islevelset){
     58                iomodel->FetchDataToInput(elements,IceMaskNodeActivationEnum);
     59        }
     60
    1061}/*}}}*/
    1162void DamageEvolutionAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
     
    4596
    4697}/*}}}*/
    47 void DamageEvolutionAnalysis::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/
    48 
    49         int finiteelement;
    50         bool   islevelset;
    51 
    52         iomodel->Constant(&finiteelement,DamageElementinterpEnum);
    53         iomodel->Constant(&islevelset,TransientIslevelsetEnum);
    54 
    55         /*Update elements: */
    56         int counter=0;
    57         for(int i=0;i<iomodel->numberofelements;i++){
    58                 if(iomodel->my_elements[i]){
    59                         Element* element=(Element*)elements->GetObjectByOffset(counter);
    60                         element->Update(i,iomodel,analysis_counter,analysis_type,finiteelement);
    61                         counter++;
    62                 }
    63         }
    64 
    65         /*What input do I need to run my damage evolution model?*/
    66         iomodel->FetchDataToInput(elements,VxEnum);
    67         iomodel->FetchDataToInput(elements,VyEnum);
    68         if(iomodel->domaintype==Domain3DEnum) iomodel->FetchDataToInput(elements,VzEnum);
    69         iomodel->FetchDataToInput(elements,DamageDEnum);
    70         iomodel->FetchDataToInput(elements,MaskIceLevelsetEnum);
    71         iomodel->FetchDataToInput(elements,PressureEnum);
    72 
    73         if(islevelset){
    74                 iomodel->FetchDataToInput(elements,IceMaskNodeActivationEnum);
    75         }
    76 
    77 }/*}}}*/
    78 void DamageEvolutionAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
    79 
    80         int finiteelement;
    81 
    82         iomodel->Constant(&finiteelement,DamageElementinterpEnum);
    83         ::CreateNodes(nodes,iomodel,DamageEvolutionAnalysisEnum,finiteelement);
    84 }/*}}}*/
    85 void DamageEvolutionAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
    86 
    87         int finiteelement;
    88         iomodel->Constant(&finiteelement,DamageElementinterpEnum);
    89 
    90         IoModelToConstraintsx(constraints,iomodel,DamageSpcdamageEnum,DamageEvolutionAnalysisEnum,finiteelement);
    91 
    92 }/*}}}*/
    93 void DamageEvolutionAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
    94 
    95         /*Nothing for now*/
    96 
    97 }/*}}}*/
    9898
    9999/*Finite Element Analysis*/
    100100void           DamageEvolutionAnalysis::Core(FemModel* femmodel){/*{{{*/
    101101        _error_("not implemented");
     102}/*}}}*/
     103void           DamageEvolutionAnalysis::CreateDamageFInputExp(Element* element){/*{{{*/
     104
     105        /*Intermediaries */
     106        IssmDouble epsf,stress_threshold,eps0;
     107        IssmDouble damage,B,n,epseff;
     108        IssmDouble eps_xx,eps_yy,eps_xy,eps1,eps2,epstmp;
     109        int domaintype,damagelaw;
     110
     111        /*Fetch number of vertices and allocate output*/
     112        int numnodes = element->GetNumberOfNodes();
     113        IssmDouble* f   = xNew<IssmDouble>(numnodes);
     114
     115        /*retrieve parameters:*/
     116        element->FindParam(&epsf,DamageC1Enum);
     117        element->FindParam(&stress_threshold,DamageStressThresholdEnum);
     118        element->FindParam(&domaintype,DomainTypeEnum);
     119        element->FindParam(&damagelaw,DamageLawEnum);
     120
     121        /*Compute stress tensor: */
     122        element->ComputeStrainRate();
     123
     124        /*retrieve what we need: */
     125        Input* eps_xx_input  = element->GetInput(StrainRatexxEnum);     _assert_(eps_xx_input);
     126        Input* eps_xy_input  = element->GetInput(StrainRatexyEnum);     _assert_(eps_xy_input);
     127        Input* eps_yy_input  = element->GetInput(StrainRateyyEnum);     _assert_(eps_yy_input);
     128        Input*  n_input=element->GetInput(MaterialsRheologyNEnum); _assert_(n_input);
     129        Input* damage_input = NULL;
     130        Input* B_input = NULL;
     131        if(domaintype==Domain2DhorizontalEnum){
     132                damage_input = element->GetInput(DamageDbarEnum);       _assert_(damage_input);
     133                B_input=element->GetInput(MaterialsRheologyBbarEnum); _assert_(B_input);
     134        }
     135        else{
     136                damage_input = element->GetInput(DamageDEnum);   _assert_(damage_input);
     137                B_input=element->GetInput(MaterialsRheologyBEnum); _assert_(B_input);
     138        }
     139
     140        /*Calculate damage evolution source term: */
     141        Gauss* gauss=element->NewGauss();
     142        for (int i=0;i<numnodes;i++){
     143                gauss->GaussNode(element->GetElementType(),i);
     144               
     145                eps_xx_input->GetInputValue(&eps_xx,gauss);
     146                eps_xy_input->GetInputValue(&eps_xy,gauss);
     147                eps_yy_input->GetInputValue(&eps_yy,gauss);
     148                B_input->GetInputValue(&B,gauss);
     149                n_input->GetInputValue(&n,gauss);
     150                damage_input->GetInputValue(&damage,gauss);
     151       
     152                /*Calculate principal effective strain rates*/
     153                eps1=(eps_xx+eps_yy)/2.+sqrt(pow((eps_xx-eps_yy)/2.,2)+pow(eps_xy,2));
     154                eps2=(eps_xx+eps_yy)/2.-sqrt(pow((eps_xx-eps_yy)/2.,2)+pow(eps_xy,2));
     155                if(fabs(eps2)>fabs(eps1)){epstmp=eps2; eps2=eps1; eps1=epstmp;}
     156
     157                /*Calculate effective strain rate and threshold strain rate*/
     158                epseff=1./sqrt(2.)*sqrt(eps1*eps1-eps1*eps2+eps2*eps2);
     159                eps0=pow(stress_threshold/B,n);
     160
     161                if(epseff>eps0){
     162                        f[i]=1.-pow(eps0/epseff,1./n)*exp(-(epseff-eps0)/(epsf-eps0))-damage;
     163                }
     164                else f[i]=0;
     165        }
     166
     167        /*Add input*/
     168        element->AddInput(DamageFEnum,f,element->GetElementType());
     169       
     170        /*Clean up and return*/
     171        xDelete<IssmDouble>(f);
     172        delete gauss;
     173}/*}}}*/
     174void           DamageEvolutionAnalysis::CreateDamageFInputPralong(Element* element){/*{{{*/
     175
     176        /*Intermediaries */
     177        IssmDouble c1,c2,c3,healing,stress_threshold;
     178        IssmDouble s_xx,s_xy,s_xz,s_yy,s_yz,s_zz,s1,s2,s3,stmp;
     179        IssmDouble J2s,Chi,Psi,PosPsi,NegPsi;
     180        IssmDouble damage,tau_xx,tau_xy,tau_xz,tau_yy,tau_yz,tau_zz,stressMaxPrincipal;
     181        int equivstress,domaintype,damagelaw,dim;
     182
     183        /*Fetch number of vertices and allocate output*/
     184        int numnodes = element->GetNumberOfNodes();
     185        IssmDouble* f   = xNew<IssmDouble>(numnodes);
     186
     187        /*retrieve parameters:*/
     188        element->FindParam(&c1,DamageC1Enum);
     189        element->FindParam(&c2,DamageC2Enum);
     190        element->FindParam(&c3,DamageC3Enum);
     191        element->FindParam(&healing,DamageHealingEnum);
     192        element->FindParam(&stress_threshold,DamageStressThresholdEnum);
     193        element->FindParam(&domaintype,DomainTypeEnum);
     194        element->FindParam(&damagelaw,DamageLawEnum);
     195
     196        /*Get problem dimension*/
     197        switch(domaintype){
     198                case Domain2DhorizontalEnum: dim = 2; break;
     199                case Domain3DEnum:           dim = 3; break;
     200                default: _error_("not implemented");
     201        }
     202        /*Compute stress tensor and Stress Max Principal: */
     203        element->ComputeDeviatoricStressTensor();
     204        if(dim==3){
     205                /*Only works in 3d because the pressure is defined*/
     206                element->StressMaxPrincipalCreateInput();
     207        }
     208        /*retrieve what we need: */
     209        Input* tau_xx_input  = element->GetInput(DeviatoricStressxxEnum);     _assert_(tau_xx_input);
     210        Input* tau_xy_input  = element->GetInput(DeviatoricStressxyEnum);     _assert_(tau_xy_input);
     211        Input* tau_yy_input  = element->GetInput(DeviatoricStressyyEnum);     _assert_(tau_yy_input);
     212        Input* tau_xz_input  = NULL;
     213        Input* tau_yz_input  = NULL;
     214        Input* tau_zz_input  = NULL;
     215        Input* stressMaxPrincipal_input = NULL;
     216        if(dim==3){
     217                tau_xz_input  = element->GetInput(DeviatoricStressxzEnum);     _assert_(tau_xz_input);
     218                tau_yz_input  = element->GetInput(DeviatoricStressyzEnum);     _assert_(tau_yz_input);
     219                tau_zz_input  = element->GetInput(DeviatoricStresszzEnum);     _assert_(tau_zz_input);
     220                stressMaxPrincipal_input = element->GetInput(StressMaxPrincipalEnum); _assert_(stressMaxPrincipal_input);
     221        }
     222        Input* damage_input = NULL;
     223        if(domaintype==Domain2DhorizontalEnum){
     224                damage_input = element->GetInput(DamageDbarEnum);       _assert_(damage_input);
     225        }
     226        else{
     227                damage_input = element->GetInput(DamageDEnum);   _assert_(damage_input);
     228        }
     229
     230        /*retrieve the desired type of equivalent stress*/
     231        element->FindParam(&equivstress,DamageEquivStressEnum);
     232
     233        /*Calculate damage evolution source term: */
     234        Gauss* gauss=element->NewGauss();
     235        for (int i=0;i<numnodes;i++){
     236                gauss->GaussNode(element->GetElementType(),i);
     237               
     238                damage_input->GetInputValue(&damage,gauss);
     239                tau_xx_input->GetInputValue(&tau_xx,gauss);
     240                tau_xy_input->GetInputValue(&tau_xy,gauss);
     241                tau_yy_input->GetInputValue(&tau_yy,gauss);
     242                if(dim==3){
     243                        tau_xz_input->GetInputValue(&tau_xz,gauss);
     244                        tau_yz_input->GetInputValue(&tau_yz,gauss);
     245                        tau_zz_input->GetInputValue(&tau_zz,gauss);
     246                }
     247                /*Calculate effective stress components*/
     248                s_xx=tau_xx/(1.-damage);
     249                s_xy=tau_xy/(1.-damage);
     250                s_yy=tau_yy/(1.-damage);
     251                if(dim==3){
     252                        s_xz=tau_xz/(1.-damage);
     253                        s_yz=tau_yz/(1.-damage);
     254                        s_zz=tau_zz/(1.-damage);
     255                }
     256                /*Calculate principal effective stresses*/
     257                if(dim==2){
     258                        s1=(s_xx+s_yy)/2.+sqrt(pow((s_xx-s_yy)/2.,2)+pow(s_xy,2));
     259                        s2=(s_xx+s_yy)/2.-sqrt(pow((s_xx-s_yy)/2.,2)+pow(s_xy,2));
     260                        if(fabs(s2)>fabs(s1)){stmp=s2; s2=s1; s1=stmp;}
     261
     262                        if(equivstress==0){ /* von Mises */
     263                                Chi=sqrt(s1*s1-s1*s2+s2*s2);
     264                        }
     265                        else if(equivstress==1){ /* max principal stress */
     266                                Chi=s1;
     267                        }
     268                        Psi=Chi-stress_threshold;
     269                        NegPsi=max(-Chi,0.); /* healing only for compressive stresses */
     270
     271                        if(damagelaw==1){
     272                                PosPsi=max(Psi,0.);
     273                                f[i]= c1*(pow(PosPsi,c2) - healing*pow(NegPsi,c2))*pow((1./(1.-damage)),c3);
     274                        }
     275                        else if(damagelaw==2){
     276                                PosPsi=max(Psi,1.);
     277                                f[i]= c1*(pow(log10(PosPsi),c2) - healing*pow(NegPsi,c2))*pow((1./(1.-damage)),c3);
     278                        }
     279                        else _error_("damage law not supported");
     280                }
     281                else{
     282                        if(equivstress==1){/* max principal stress */
     283                                stressMaxPrincipal_input->GetInputValue(&stressMaxPrincipal,gauss);
     284                                Chi=stressMaxPrincipal/(1.-damage);
     285                        }
     286                        else if(equivstress==0){/* von Mises */
     287                                Chi=sqrt(((s_xx-s_yy)*(s_xx-s_yy)+(s_yy-s_zz)*(s_yy-s_zz)+(s_zz-s_xx)*(s_zz-s_xx)+6.*(s_xy*s_xy+s_yz*s_yz+s_xz*s_xz))/2.);
     288                        }
     289                        Psi=Chi-stress_threshold;
     290                        NegPsi=max(-Chi,0.); /* healing only for compressive stresses */
     291                        if(damagelaw==1){
     292                                PosPsi=max(Psi,0.);
     293                                f[i]= c1*(pow(PosPsi,c2) - healing*pow(NegPsi,c2))*pow((1./(1.-damage)),c3);
     294                        }
     295                        else if(damagelaw==2){
     296                                PosPsi=max(Psi,1.);
     297                                f[i]= c1*(pow(log10(PosPsi),c2) - healing*pow(NegPsi,c2))*pow((1./(1.-damage)),c3);
     298                        }
     299                        else _error_("damage law not supported");
     300                }
     301        }
     302        /*Add input*/
     303        element->AddInput(DamageFEnum,f,element->GetElementType());
     304       
     305        /*Clean up and return*/
     306        xDelete<IssmDouble>(f);
     307        delete gauss;
    102308}/*}}}*/
    103309ElementVector* DamageEvolutionAnalysis::CreateDVector(Element* element){/*{{{*/
     
    342548        return pe;
    343549}/*}}}*/
    344 void DamageEvolutionAnalysis::GetB(IssmDouble* B,Element* element,int dim,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
     550void           DamageEvolutionAnalysis::GetB(IssmDouble* B,Element* element,int dim,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
    345551        /*Compute B  matrix. B=[B1 B2 B3] where Bi is of size 3*NDOF2.
    346552         * For node i, Bi can be expressed in the actual coordinate system
     
    370576        xDelete<IssmDouble>(basis);
    371577}/*}}}*/
    372 void DamageEvolutionAnalysis::GetBprime(IssmDouble* Bprime,Element* element,int dim,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
     578void           DamageEvolutionAnalysis::GetBprime(IssmDouble* Bprime,Element* element,int dim,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
    373579        /*Compute B'  matrix. B'=[B1' B2' B3'] where Bi' is of size 3*NDOF2.
    374580         * For node i, Bi' can be expressed in the actual coordinate system
     
    399605
    400606}/*}}}*/
    401 void DamageEvolutionAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
     607void           DamageEvolutionAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
    402608           _error_("not implemented yet");
    403609}/*}}}*/
    404 void DamageEvolutionAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
     610void           DamageEvolutionAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
    405611        _error_("Not implemented yet");
    406612}/*}}}*/
    407 void DamageEvolutionAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
     613void           DamageEvolutionAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
    408614
    409615        int domaintype;
     
    445651        xDelete<int>(doflist);
    446652}/*}}}*/
    447 void DamageEvolutionAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
     653void           DamageEvolutionAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
    448654        /*Default, do nothing*/
    449655        bool islevelset;
     
    454660        return;
    455661}/*}}}*/
    456 
    457 /*Intermediaries*/
    458 void DamageEvolutionAnalysis::CreateDamageFInputPralong(Element* element){/*{{{*/
    459 
    460         /*Intermediaries */
    461         IssmDouble c1,c2,c3,healing,stress_threshold;
    462         IssmDouble s_xx,s_xy,s_xz,s_yy,s_yz,s_zz,s1,s2,s3,stmp;
    463         IssmDouble J2s,Chi,Psi,PosPsi,NegPsi;
    464         IssmDouble damage,tau_xx,tau_xy,tau_xz,tau_yy,tau_yz,tau_zz,stressMaxPrincipal;
    465         int equivstress,domaintype,damagelaw,dim;
    466 
    467         /*Fetch number of vertices and allocate output*/
    468         int numnodes = element->GetNumberOfNodes();
    469         IssmDouble* f   = xNew<IssmDouble>(numnodes);
    470 
    471         /*retrieve parameters:*/
    472         element->FindParam(&c1,DamageC1Enum);
    473         element->FindParam(&c2,DamageC2Enum);
    474         element->FindParam(&c3,DamageC3Enum);
    475         element->FindParam(&healing,DamageHealingEnum);
    476         element->FindParam(&stress_threshold,DamageStressThresholdEnum);
    477         element->FindParam(&domaintype,DomainTypeEnum);
    478         element->FindParam(&damagelaw,DamageLawEnum);
    479 
    480         /*Get problem dimension*/
    481         switch(domaintype){
    482                 case Domain2DhorizontalEnum: dim = 2; break;
    483                 case Domain3DEnum:           dim = 3; break;
    484                 default: _error_("not implemented");
    485         }
    486         /*Compute stress tensor and Stress Max Principal: */
    487         element->ComputeDeviatoricStressTensor();
    488         if(dim==3){
    489                 /*Only works in 3d because the pressure is defined*/
    490                 element->StressMaxPrincipalCreateInput();
    491         }
    492         /*retrieve what we need: */
    493         Input* tau_xx_input  = element->GetInput(DeviatoricStressxxEnum);     _assert_(tau_xx_input);
    494         Input* tau_xy_input  = element->GetInput(DeviatoricStressxyEnum);     _assert_(tau_xy_input);
    495         Input* tau_yy_input  = element->GetInput(DeviatoricStressyyEnum);     _assert_(tau_yy_input);
    496         Input* tau_xz_input  = NULL;
    497         Input* tau_yz_input  = NULL;
    498         Input* tau_zz_input  = NULL;
    499         Input* stressMaxPrincipal_input = NULL;
    500         if(dim==3){
    501                 tau_xz_input  = element->GetInput(DeviatoricStressxzEnum);     _assert_(tau_xz_input);
    502                 tau_yz_input  = element->GetInput(DeviatoricStressyzEnum);     _assert_(tau_yz_input);
    503                 tau_zz_input  = element->GetInput(DeviatoricStresszzEnum);     _assert_(tau_zz_input);
    504                 stressMaxPrincipal_input = element->GetInput(StressMaxPrincipalEnum); _assert_(stressMaxPrincipal_input);
    505         }
    506         Input* damage_input = NULL;
    507         if(domaintype==Domain2DhorizontalEnum){
    508                 damage_input = element->GetInput(DamageDbarEnum);       _assert_(damage_input);
    509         }
    510         else{
    511                 damage_input = element->GetInput(DamageDEnum);   _assert_(damage_input);
    512         }
    513 
    514         /*retrieve the desired type of equivalent stress*/
    515         element->FindParam(&equivstress,DamageEquivStressEnum);
    516 
    517         /*Calculate damage evolution source term: */
    518         Gauss* gauss=element->NewGauss();
    519         for (int i=0;i<numnodes;i++){
    520                 gauss->GaussNode(element->GetElementType(),i);
    521                
    522                 damage_input->GetInputValue(&damage,gauss);
    523                 tau_xx_input->GetInputValue(&tau_xx,gauss);
    524                 tau_xy_input->GetInputValue(&tau_xy,gauss);
    525                 tau_yy_input->GetInputValue(&tau_yy,gauss);
    526                 if(dim==3){
    527                         tau_xz_input->GetInputValue(&tau_xz,gauss);
    528                         tau_yz_input->GetInputValue(&tau_yz,gauss);
    529                         tau_zz_input->GetInputValue(&tau_zz,gauss);
    530                 }
    531                 /*Calculate effective stress components*/
    532                 s_xx=tau_xx/(1.-damage);
    533                 s_xy=tau_xy/(1.-damage);
    534                 s_yy=tau_yy/(1.-damage);
    535                 if(dim==3){
    536                         s_xz=tau_xz/(1.-damage);
    537                         s_yz=tau_yz/(1.-damage);
    538                         s_zz=tau_zz/(1.-damage);
    539                 }
    540                 /*Calculate principal effective stresses*/
    541                 if(dim==2){
    542                         s1=(s_xx+s_yy)/2.+sqrt(pow((s_xx-s_yy)/2.,2)+pow(s_xy,2));
    543                         s2=(s_xx+s_yy)/2.-sqrt(pow((s_xx-s_yy)/2.,2)+pow(s_xy,2));
    544                         if(fabs(s2)>fabs(s1)){stmp=s2; s2=s1; s1=stmp;}
    545 
    546                         if(equivstress==0){ /* von Mises */
    547                                 Chi=sqrt(s1*s1-s1*s2+s2*s2);
    548                         }
    549                         else if(equivstress==1){ /* max principal stress */
    550                                 Chi=s1;
    551                         }
    552                         Psi=Chi-stress_threshold;
    553                         NegPsi=max(-Chi,0.); /* healing only for compressive stresses */
    554 
    555                         if(damagelaw==1){
    556                                 PosPsi=max(Psi,0.);
    557                                 f[i]= c1*(pow(PosPsi,c2) - healing*pow(NegPsi,c2))*pow((1./(1.-damage)),c3);
    558                         }
    559                         else if(damagelaw==2){
    560                                 PosPsi=max(Psi,1.);
    561                                 f[i]= c1*(pow(log10(PosPsi),c2) - healing*pow(NegPsi,c2))*pow((1./(1.-damage)),c3);
    562                         }
    563                         else _error_("damage law not supported");
    564                 }
    565                 else{
    566                         if(equivstress==1){/* max principal stress */
    567                                 stressMaxPrincipal_input->GetInputValue(&stressMaxPrincipal,gauss);
    568                                 Chi=stressMaxPrincipal/(1.-damage);
    569                         }
    570                         else if(equivstress==0){/* von Mises */
    571                                 Chi=sqrt(((s_xx-s_yy)*(s_xx-s_yy)+(s_yy-s_zz)*(s_yy-s_zz)+(s_zz-s_xx)*(s_zz-s_xx)+6.*(s_xy*s_xy+s_yz*s_yz+s_xz*s_xz))/2.);
    572                         }
    573                         Psi=Chi-stress_threshold;
    574                         NegPsi=max(-Chi,0.); /* healing only for compressive stresses */
    575                         if(damagelaw==1){
    576                                 PosPsi=max(Psi,0.);
    577                                 f[i]= c1*(pow(PosPsi,c2) - healing*pow(NegPsi,c2))*pow((1./(1.-damage)),c3);
    578                         }
    579                         else if(damagelaw==2){
    580                                 PosPsi=max(Psi,1.);
    581                                 f[i]= c1*(pow(log10(PosPsi),c2) - healing*pow(NegPsi,c2))*pow((1./(1.-damage)),c3);
    582                         }
    583                         else _error_("damage law not supported");
    584                 }
    585         }
    586         /*Add input*/
    587         element->AddInput(DamageFEnum,f,element->GetElementType());
    588        
    589         /*Clean up and return*/
    590         xDelete<IssmDouble>(f);
    591         delete gauss;
    592 }/*}}}*/
    593 void DamageEvolutionAnalysis::CreateDamageFInputExp(Element* element){/*{{{*/
    594 
    595         /*Intermediaries */
    596         IssmDouble epsf,stress_threshold,eps0;
    597         IssmDouble damage,B,n,epseff;
    598         IssmDouble eps_xx,eps_yy,eps_xy,eps1,eps2,epstmp;
    599         int domaintype,damagelaw;
    600 
    601         /*Fetch number of vertices and allocate output*/
    602         int numnodes = element->GetNumberOfNodes();
    603         IssmDouble* f   = xNew<IssmDouble>(numnodes);
    604 
    605         /*retrieve parameters:*/
    606         element->FindParam(&epsf,DamageC1Enum);
    607         element->FindParam(&stress_threshold,DamageStressThresholdEnum);
    608         element->FindParam(&domaintype,DomainTypeEnum);
    609         element->FindParam(&damagelaw,DamageLawEnum);
    610 
    611         /*Compute stress tensor: */
    612         element->ComputeStrainRate();
    613 
    614         /*retrieve what we need: */
    615         Input* eps_xx_input  = element->GetInput(StrainRatexxEnum);     _assert_(eps_xx_input);
    616         Input* eps_xy_input  = element->GetInput(StrainRatexyEnum);     _assert_(eps_xy_input);
    617         Input* eps_yy_input  = element->GetInput(StrainRateyyEnum);     _assert_(eps_yy_input);
    618         Input*  n_input=element->GetInput(MaterialsRheologyNEnum); _assert_(n_input);
    619         Input* damage_input = NULL;
    620         Input* B_input = NULL;
    621         if(domaintype==Domain2DhorizontalEnum){
    622                 damage_input = element->GetInput(DamageDbarEnum);       _assert_(damage_input);
    623                 B_input=element->GetInput(MaterialsRheologyBbarEnum); _assert_(B_input);
    624         }
    625         else{
    626                 damage_input = element->GetInput(DamageDEnum);   _assert_(damage_input);
    627                 B_input=element->GetInput(MaterialsRheologyBEnum); _assert_(B_input);
    628         }
    629 
    630         /*Calculate damage evolution source term: */
    631         Gauss* gauss=element->NewGauss();
    632         for (int i=0;i<numnodes;i++){
    633                 gauss->GaussNode(element->GetElementType(),i);
    634                
    635                 eps_xx_input->GetInputValue(&eps_xx,gauss);
    636                 eps_xy_input->GetInputValue(&eps_xy,gauss);
    637                 eps_yy_input->GetInputValue(&eps_yy,gauss);
    638                 B_input->GetInputValue(&B,gauss);
    639                 n_input->GetInputValue(&n,gauss);
    640                 damage_input->GetInputValue(&damage,gauss);
    641        
    642                 /*Calculate principal effective strain rates*/
    643                 eps1=(eps_xx+eps_yy)/2.+sqrt(pow((eps_xx-eps_yy)/2.,2)+pow(eps_xy,2));
    644                 eps2=(eps_xx+eps_yy)/2.-sqrt(pow((eps_xx-eps_yy)/2.,2)+pow(eps_xy,2));
    645                 if(fabs(eps2)>fabs(eps1)){epstmp=eps2; eps2=eps1; eps1=epstmp;}
    646 
    647                 /*Calculate effective strain rate and threshold strain rate*/
    648                 epseff=1./sqrt(2.)*sqrt(eps1*eps1-eps1*eps2+eps2*eps2);
    649                 eps0=pow(stress_threshold/B,n);
    650 
    651                 if(epseff>eps0){
    652                         f[i]=1.-pow(eps0/epseff,1./n)*exp(-(epseff-eps0)/(epsf-eps0))-damage;
    653                 }
    654                 else f[i]=0;
    655         }
    656 
    657         /*Add input*/
    658         element->AddInput(DamageFEnum,f,element->GetElementType());
    659        
    660         /*Clean up and return*/
    661         xDelete<IssmDouble>(f);
    662         delete gauss;
    663 }/*}}}*/
  • issm/trunk-jpl/src/c/analyses/DamageEvolutionAnalysis.h

    r18136 r18930  
    1313        public:
    1414                /*Model processing*/
    15                 int  DofsPerNode(int** doflist,int domaintype,int approximation);
    16                 void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);
    17                 void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);
    18                 void CreateNodes(Nodes* nodes,IoModel* iomodel);
    1915                void CreateConstraints(Constraints* constraints,IoModel* iomodel);
    2016                void CreateLoads(Loads* loads, IoModel* iomodel);
     17                void CreateNodes(Nodes* nodes,IoModel* iomodel);
     18                int  DofsPerNode(int** doflist,int domaintype,int approximation);
     19                void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);
     20                void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);
    2121
    2222                /*Finite element Analysis*/
    2323                void           Core(FemModel* femmodel);
     24                void           CreateDamageFInputExp(Element* element);
     25                void           CreateDamageFInputPralong(Element* element);
    2426                ElementVector* CreateDVector(Element* element);
    2527                ElementMatrix* CreateJacobianMatrix(Element* element);
    2628                ElementMatrix* CreateKMatrix(Element* element);
    2729                ElementVector* CreatePVector(Element* element);
    28                 void GetB(IssmDouble* B,Element* element,int dim,IssmDouble* xyz_list,Gauss* gauss);
    29                 void GetBprime(IssmDouble* B,Element* element,int dim,IssmDouble* xyz_list,Gauss* gauss);
    30                 void GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);
    31                 void GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);
    32                 void InputUpdateFromSolution(IssmDouble* solution,Element* element);
    33                 void UpdateConstraints(FemModel* femmodel);
    34 
    35                 /*Intermediaries*/
    36                 void CreateDamageFInputPralong(Element* element);
    37                 void CreateDamageFInputExp(Element* element);
     30                void           GetB(IssmDouble* B,Element* element,int dim,IssmDouble* xyz_list,Gauss* gauss);
     31                void           GetBprime(IssmDouble* B,Element* element,int dim,IssmDouble* xyz_list,Gauss* gauss);
     32                void           GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);
     33                void           GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);
     34                void           InputUpdateFromSolution(IssmDouble* solution,Element* element);
     35                void           UpdateConstraints(FemModel* femmodel);
    3836};
    3937#endif
  • issm/trunk-jpl/src/c/analyses/EnthalpyAnalysis.cpp

    r18804 r18930  
    77
    88/*Model processing*/
     9void EnthalpyAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
     10
     11        /*Intermediary*/
     12        int        count;
     13        int        M,N;
     14        bool       spcpresent = false;
     15        IssmDouble heatcapacity;
     16        IssmDouble referencetemperature;
     17
     18        /*Output*/
     19        IssmDouble *spcvector  = NULL;
     20        IssmDouble* times=NULL;
     21        IssmDouble* values=NULL;
     22
     23        /*Fetch parameters: */
     24        iomodel->Constant(&heatcapacity,MaterialsHeatcapacityEnum);
     25        iomodel->Constant(&referencetemperature,ConstantsReferencetemperatureEnum);
     26
     27        /*return if 2d mesh*/
     28        if(iomodel->domaintype==Domain2DhorizontalEnum) return;
     29
     30        /*Fetch data: */
     31        iomodel->FetchData(&spcvector,&M,&N,ThermalSpctemperatureEnum);
     32
     33        //FIX ME: SHOULD USE IOMODELCREATECONSTRAINTS
     34        /*Transient or static?:*/
     35        if(M==iomodel->numberofvertices){
     36                /*static: just create Constraints objects*/
     37                count=0;
     38
     39                for(int i=0;i<iomodel->numberofvertices;i++){
     40                        /*keep only this partition's nodes:*/
     41                        if((iomodel->my_vertices[i])){
     42
     43                                if (!xIsNan<IssmDouble>(spcvector[i])){
     44
     45                                        constraints->AddObject(new SpcStatic(iomodel->constraintcounter+count+1,iomodel->nodecounter+i+1,0,heatcapacity*(spcvector[i]-referencetemperature),EnthalpyAnalysisEnum));
     46                                        count++;
     47
     48                                }
     49                        }
     50                }
     51        }
     52        else if (M==(iomodel->numberofvertices+1)){
     53                /*transient: create transient SpcTransient objects. Same logic, except we need to retrieve
     54                 * various times and values to initialize an SpcTransient object: */
     55                count=0;
     56
     57                /*figure out times: */
     58                times=xNew<IssmDouble>(N);
     59                for(int j=0;j<N;j++){
     60                        times[j]=spcvector[(M-1)*N+j];
     61                }
     62
     63                /*Create constraints from x,y,z: */
     64                for(int i=0;i<iomodel->numberofvertices;i++){
     65
     66                        /*keep only this partition's nodes:*/
     67                        if((iomodel->my_vertices[i])){
     68
     69                                /*figure out times and values: */
     70                                values=xNew<IssmDouble>(N);
     71                                spcpresent=false;
     72                                for(int j=0;j<N;j++){
     73                                        values[j]=heatcapacity*(spcvector[i*N+j]-referencetemperature);
     74                                        if(!xIsNan<IssmDouble>(values[j]))spcpresent=true; //NaN means no spc by default
     75                                }
     76
     77                                if(spcpresent){
     78                                        constraints->AddObject(new SpcTransient(iomodel->constraintcounter+count+1,iomodel->nodecounter+i+1,0,N,times,values,EnthalpyAnalysisEnum));
     79                                        count++;
     80                                }
     81                                xDelete<IssmDouble>(values);
     82                        }
     83                }
     84        }
     85        else{
     86                _error_("Size of field " << EnumToStringx(ThermalSpctemperatureEnum) << " not supported");
     87        }
     88
     89        /*Free ressources:*/
     90        iomodel->DeleteData(spcvector,ThermalSpctemperatureEnum);
     91        xDelete<IssmDouble>(times);
     92        xDelete<IssmDouble>(values);
     93}/*}}}*/
     94void EnthalpyAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
     95
     96        /*No loads */
     97}/*}}}*/
     98void EnthalpyAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
     99
     100        if(iomodel->domaintype==Domain3DEnum) iomodel->FetchData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum);
     101        ::CreateNodes(nodes,iomodel,EnthalpyAnalysisEnum,P1Enum);
     102        iomodel->DeleteData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum);
     103}/*}}}*/
    9104int  EnthalpyAnalysis::DofsPerNode(int** doflist,int domaintype,int approximation){/*{{{*/
    10105        return 1;
    11 }/*}}}*/
    12 void EnthalpyAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
    13 
    14         int     numoutputs;
    15         char**  requestedoutputs = NULL;
    16 
    17         parameters->AddObject(iomodel->CopyConstantObject(ThermalStabilizationEnum));
    18         parameters->AddObject(iomodel->CopyConstantObject(ThermalMaxiterEnum));
    19         parameters->AddObject(iomodel->CopyConstantObject(ThermalReltolEnum));
    20         parameters->AddObject(iomodel->CopyConstantObject(ThermalIsenthalpyEnum));
    21         parameters->AddObject(iomodel->CopyConstantObject(ThermalIsdynamicbasalspcEnum));
    22         parameters->AddObject(iomodel->CopyConstantObject(FrictionLawEnum));
    23 
    24         iomodel->FetchData(&requestedoutputs,&numoutputs,ThermalRequestedOutputsEnum);
    25         parameters->AddObject(new IntParam(ThermalNumRequestedOutputsEnum,numoutputs));
    26         if(numoutputs)parameters->AddObject(new StringArrayParam(ThermalRequestedOutputsEnum,requestedoutputs,numoutputs));
    27         iomodel->DeleteData(&requestedoutputs,numoutputs,ThermalRequestedOutputsEnum);
    28 
    29         /*Deal with friction parameters*/
    30         int frictionlaw;
    31         iomodel->Constant(&frictionlaw,FrictionLawEnum);
    32         if(frictionlaw==4 || frictionlaw==6) parameters->AddObject(iomodel->CopyConstantObject(FrictionGammaEnum));
    33106}/*}}}*/
    34107void EnthalpyAnalysis::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/
     
    132205        iomodel->DeleteData(3,TemperatureEnum,WaterfractionEnum,PressureEnum);
    133206}/*}}}*/
    134 void EnthalpyAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
    135 
    136         if(iomodel->domaintype==Domain3DEnum) iomodel->FetchData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum);
    137         ::CreateNodes(nodes,iomodel,EnthalpyAnalysisEnum,P1Enum);
    138         iomodel->DeleteData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum);
    139 }/*}}}*/
    140 void EnthalpyAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
     207void EnthalpyAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
     208
     209        int     numoutputs;
     210        char**  requestedoutputs = NULL;
     211
     212        parameters->AddObject(iomodel->CopyConstantObject(ThermalStabilizationEnum));
     213        parameters->AddObject(iomodel->CopyConstantObject(ThermalMaxiterEnum));
     214        parameters->AddObject(iomodel->CopyConstantObject(ThermalReltolEnum));
     215        parameters->AddObject(iomodel->CopyConstantObject(ThermalIsenthalpyEnum));
     216        parameters->AddObject(iomodel->CopyConstantObject(ThermalIsdynamicbasalspcEnum));
     217        parameters->AddObject(iomodel->CopyConstantObject(FrictionLawEnum));
     218
     219        iomodel->FetchData(&requestedoutputs,&numoutputs,ThermalRequestedOutputsEnum);
     220        parameters->AddObject(new IntParam(ThermalNumRequestedOutputsEnum,numoutputs));
     221        if(numoutputs)parameters->AddObject(new StringArrayParam(ThermalRequestedOutputsEnum,requestedoutputs,numoutputs));
     222        iomodel->DeleteData(&requestedoutputs,numoutputs,ThermalRequestedOutputsEnum);
     223
     224        /*Deal with friction parameters*/
     225        int frictionlaw;
     226        iomodel->Constant(&frictionlaw,FrictionLawEnum);
     227        if(frictionlaw==4 || frictionlaw==6) parameters->AddObject(iomodel->CopyConstantObject(FrictionGammaEnum));
     228}/*}}}*/
     229
     230/*Finite Element Analysis*/
     231void           EnthalpyAnalysis::ApplyBasalConstraints(IssmDouble* serial_spc,Element* element){/*{{{*/
     232
     233        /* Check if ice in element */
     234        if(!element->IsIceInElement()) return;
     235
     236        /* Only update Constraints at the base of grounded ice*/
     237        if(!(element->IsOnBase()) || element->IsFloating()) return;
    141238
    142239        /*Intermediary*/
    143         int        count;
    144         int        M,N;
    145         bool       spcpresent = false;
    146         IssmDouble heatcapacity;
    147         IssmDouble referencetemperature;
    148 
    149         /*Output*/
    150         IssmDouble *spcvector  = NULL;
    151         IssmDouble* times=NULL;
    152         IssmDouble* values=NULL;
    153 
    154         /*Fetch parameters: */
    155         iomodel->Constant(&heatcapacity,MaterialsHeatcapacityEnum);
    156         iomodel->Constant(&referencetemperature,ConstantsReferencetemperatureEnum);
    157 
    158         /*return if 2d mesh*/
    159         if(iomodel->domaintype==Domain2DhorizontalEnum) return;
    160 
    161         /*Fetch data: */
    162         iomodel->FetchData(&spcvector,&M,&N,ThermalSpctemperatureEnum);
    163 
    164         //FIX ME: SHOULD USE IOMODELCREATECONSTRAINTS
    165         /*Transient or static?:*/
    166         if(M==iomodel->numberofvertices){
    167                 /*static: just create Constraints objects*/
    168                 count=0;
    169 
    170                 for(int i=0;i<iomodel->numberofvertices;i++){
    171                         /*keep only this partition's nodes:*/
    172                         if((iomodel->my_vertices[i])){
    173 
    174                                 if (!xIsNan<IssmDouble>(spcvector[i])){
    175 
    176                                         constraints->AddObject(new SpcStatic(iomodel->constraintcounter+count+1,iomodel->nodecounter+i+1,0,heatcapacity*(spcvector[i]-referencetemperature),EnthalpyAnalysisEnum));
    177                                         count++;
    178 
    179                                 }
     240        bool        isdynamicbasalspc;
     241        int         numindices;
     242        int        *indices = NULL;
     243        Node*       node = NULL;
     244        IssmDouble      pressure;
     245
     246        /*Check wether dynamic basal boundary conditions are activated */
     247        element->FindParam(&isdynamicbasalspc,ThermalIsdynamicbasalspcEnum);
     248        if(!isdynamicbasalspc) return;
     249
     250        /*Get parameters and inputs: */
     251        Input* pressure_input            = element->GetInput(PressureEnum);                                                      _assert_(pressure_input);
     252
     253        /*Fetch indices of basal & surface nodes for this finite element*/
     254        Penta *penta =  (Penta *) element; // TODO: add Basal-/SurfaceNodeIndices to element.h, and change this to Element*
     255        penta->BasalNodeIndices(&numindices,&indices,element->GetElementType());
     256
     257        GaussPenta* gauss=new GaussPenta();
     258        for(int i=0;i<numindices;i++){
     259                gauss->GaussNode(element->GetElementType(),indices[i]);
     260
     261                pressure_input->GetInputValue(&pressure,gauss);
     262
     263                /*apply or release spc*/
     264                node=element->GetNode(indices[i]);
     265                if(serial_spc[node->Sid()]==1.){
     266                        pressure_input->GetInputValue(&pressure, gauss);
     267                        node->ApplyConstraint(0,PureIceEnthalpy(element,pressure));
     268                }
     269                else                   
     270                        node->DofInFSet(0);
     271        }
     272
     273        /*Free ressources:*/
     274        xDelete<int>(indices);
     275        delete gauss;
     276}/*}}}*/
     277void           EnthalpyAnalysis::ComputeBasalMeltingrate(FemModel* femmodel){/*{{{*/
     278        /*Compute basal melting rates: */
     279        for(int i=0;i<femmodel->elements->Size();i++){
     280                Element* element=xDynamicCast<Element*>(femmodel->elements->GetObjectByOffset(i));
     281                ComputeBasalMeltingrate(element);
     282        }
     283}/*}}}*/
     284void           EnthalpyAnalysis::ComputeBasalMeltingrate(Element* element){/*{{{*/
     285        /*Calculate the basal melt rates of the enthalpy model after Aschwanden 2012*/
     286        /* melting rate is positive when melting, negative when refreezing*/
     287
     288        /* Check if ice in element */
     289        if(!element->IsIceInElement()) return;
     290
     291        /* Only compute melt rates at the base of grounded ice*/
     292        if(!element->IsOnBase() || element->IsFloating()) return;
     293
     294        /* Intermediaries */
     295        bool                    converged;
     296        const int   dim=3;
     297        int         i,is,state;
     298        int                     vertexdown,vertexup,numvertices,numsegments;
     299        int                     enthalpy_enum;
     300        IssmDouble  vec_heatflux[dim],normal_base[dim],d1enthalpy[dim],d1pressure[dim];
     301        IssmDouble  basalfriction,alpha2,geothermalflux,heatflux;
     302        IssmDouble  dt,yts;
     303        IssmDouble  melting_overshoot,lambda;
     304        IssmDouble  vx,vy,vz;
     305        IssmDouble *xyz_list      = NULL;
     306        IssmDouble *xyz_list_base = NULL;
     307        int        *pairindices   = NULL;
     308
     309        /*Fetch parameters*/
     310        element->GetVerticesCoordinates(&xyz_list);
     311        element->GetVerticesCoordinatesBase(&xyz_list_base);
     312        element->GetInputValue(&converged,ConvergedEnum);
     313        element->FindParam(&dt,TimesteppingTimeStepEnum);
     314        element->FindParam(&yts, ConstantsYtsEnum);
     315
     316        if(dt==0. && !converged) enthalpy_enum=EnthalpyPicardEnum;
     317        else enthalpy_enum=EnthalpyEnum;
     318
     319        IssmDouble latentheat = element->GetMaterialParameter(MaterialsLatentheatEnum);
     320        IssmDouble rho_ice    = element->GetMaterialParameter(MaterialsRhoIceEnum);
     321        IssmDouble rho_water  = element->GetMaterialParameter(MaterialsRhoFreshwaterEnum);
     322        IssmDouble beta          = element->GetMaterialParameter(MaterialsBetaEnum);
     323        IssmDouble kappa                 = EnthalpyDiffusionParameterVolume(element,enthalpy_enum);     _assert_(kappa>=0.);
     324        IssmDouble kappa_mix;
     325
     326        /*retrieve inputs*/
     327        Input* enthalpy_input         = element->GetInput(enthalpy_enum);                    _assert_(enthalpy_input);
     328        Input* pressure_input                   = element->GetInput(PressureEnum);                                                       _assert_(pressure_input);
     329        Input* geothermalflux_input   = element->GetInput(BasalforcingsGeothermalfluxEnum); _assert_(geothermalflux_input);
     330        Input* vx_input               = element->GetInput(VxEnum);                          _assert_(vx_input);
     331        Input* vy_input               = element->GetInput(VyEnum);                          _assert_(vy_input);
     332        Input* vz_input               = element->GetInput(VzEnum);                          _assert_(vz_input);
     333
     334        /*Build friction element, needed later: */
     335        Friction* friction=new Friction(element,dim);
     336
     337        /******** MELTING RATES  ************************************//*{{{*/
     338        element->NormalBase(&normal_base[0],xyz_list_base);
     339        element->VerticalSegmentIndices(&pairindices,&numsegments);
     340        IssmDouble* meltingrate_enthalpy = xNew<IssmDouble>(numsegments);
     341        IssmDouble* heating = xNew<IssmDouble>(numsegments);   
     342
     343        numvertices=element->GetNumberOfVertices();
     344        IssmDouble* enthalpies = xNew<IssmDouble>(numvertices);
     345        IssmDouble* pressures = xNew<IssmDouble>(numvertices);
     346        IssmDouble* watercolumns = xNew<IssmDouble>(numvertices);
     347        IssmDouble* basalmeltingrates = xNew<IssmDouble>(numvertices);
     348        element->GetInputListOnVertices(enthalpies,enthalpy_enum);
     349        element->GetInputListOnVertices(pressures,PressureEnum);
     350        element->GetInputListOnVertices(watercolumns,WatercolumnEnum);
     351        element->GetInputListOnVertices(basalmeltingrates,BasalforcingsGroundediceMeltingRateEnum);
     352
     353        Gauss* gauss=element->NewGauss();
     354        for(is=0;is<numsegments;is++){
     355                vertexdown = pairindices[is*2+0];
     356                vertexup   = pairindices[is*2+1];
     357                gauss->GaussVertex(vertexdown);
     358
     359                state=GetThermalBasalCondition(element, enthalpies[vertexdown], enthalpies[vertexup], pressures[vertexdown], pressures[vertexup], watercolumns[vertexdown], basalmeltingrates[vertexdown]);
     360                switch (state) {
     361                        case 0:
     362                                // cold, dry base: apply basal surface forcing
     363                                for(i=0;i<3;i++) vec_heatflux[i]=0.;
     364                                break;
     365                        case 1: case 2: case 3:
     366                                // case 1 : cold, wet base: keep at pressure melting point
     367                                // case 2: temperate, thin refreezing base: release spc
     368                                // case 3: temperate, thin melting base: set spc
     369                                enthalpy_input->GetInputDerivativeValue(&d1enthalpy[0],xyz_list,gauss);
     370                                for(i=0;i<3;i++) vec_heatflux[i]=-kappa*d1enthalpy[i];
     371                                break;
     372                        case 4:
     373                                // temperate, thick melting base: set grad H*n=0
     374                                kappa_mix=GetWetIceConductivity(element, enthalpies[vertexdown], pressures[vertexdown]);
     375                                pressure_input->GetInputDerivativeValue(&d1pressure[0],xyz_list,gauss);
     376                                for(i=0;i<3;i++) vec_heatflux[i]=kappa_mix*beta*d1pressure[i];
     377                                break;
     378                        default:
     379                                _printf0_("     unknown thermal basal state found!");
     380                }
     381                if(state==0) meltingrate_enthalpy[is]=0.;
     382                else{
     383                        /*heat flux along normal*/
     384                        heatflux=0.;
     385                        for(i=0;i<3;i++) heatflux+=(vec_heatflux[i])*normal_base[i];
     386
     387                        /*basal friction*/
     388                        friction->GetAlpha2(&alpha2,gauss);
     389                        vx_input->GetInputValue(&vx,gauss);             vy_input->GetInputValue(&vy,gauss);             vz_input->GetInputValue(&vz,gauss);
     390                        basalfriction=alpha2*(vx*vx + vy*vy + vz*vz);
     391                        geothermalflux_input->GetInputValue(&geothermalflux,gauss);
     392                        /* -Mb= Fb-(q-q_geo)/((1-w)*L*rho), and (1-w)*rho=rho_ice, cf Aschwanden 2012, eqs.1, 2, 66*/
     393                        heating[is]=(heatflux+basalfriction+geothermalflux);
     394                        meltingrate_enthalpy[is]=heating[is]/(latentheat*rho_ice); // m/s water equivalent
     395                }
     396        }/*}}}*/
     397
     398        /******** UPDATE MELTINGRATES AND WATERCOLUMN **************//*{{{*/
     399        for(is=0;is<numsegments;is++){
     400                vertexdown = pairindices[is*2+0];
     401                vertexup   = pairindices[is*2+1];
     402                if(dt!=0.){
     403                        if(watercolumns[vertexdown]+meltingrate_enthalpy[is]*dt<0.){    // prevent too much freeze on                   
     404                                lambda = -watercolumns[vertexdown]/(dt*meltingrate_enthalpy[is]); _assert_(lambda>=0.); _assert_(lambda<1.);
     405                                watercolumns[vertexdown]=0.;
     406                                basalmeltingrates[vertexdown]=lambda*meltingrate_enthalpy[is]; // restrict freeze on only to size of watercolumn
     407                                enthalpies[vertexdown]+=(1.-lambda)*dt/yts*meltingrate_enthalpy[is]*latentheat*rho_ice; // use rest of energy to cool down base: dE=L*m, m=(1-lambda)*meltingrate*rho_ice
    180408                        }
    181                 }
    182         }
    183         else if (M==(iomodel->numberofvertices+1)){
    184                 /*transient: create transient SpcTransient objects. Same logic, except we need to retrieve
    185                  * various times and values to initialize an SpcTransient object: */
    186                 count=0;
    187 
    188                 /*figure out times: */
    189                 times=xNew<IssmDouble>(N);
    190                 for(int j=0;j<N;j++){
    191                         times[j]=spcvector[(M-1)*N+j];
    192                 }
    193 
    194                 /*Create constraints from x,y,z: */
    195                 for(int i=0;i<iomodel->numberofvertices;i++){
    196 
    197                         /*keep only this partition's nodes:*/
    198                         if((iomodel->my_vertices[i])){
    199 
    200                                 /*figure out times and values: */
    201                                 values=xNew<IssmDouble>(N);
    202                                 spcpresent=false;
    203                                 for(int j=0;j<N;j++){
    204                                         values[j]=heatcapacity*(spcvector[i*N+j]-referencetemperature);
    205                                         if(!xIsNan<IssmDouble>(values[j]))spcpresent=true; //NaN means no spc by default
    206                                 }
    207 
    208                                 if(spcpresent){
    209                                         constraints->AddObject(new SpcTransient(iomodel->constraintcounter+count+1,iomodel->nodecounter+i+1,0,N,times,values,EnthalpyAnalysisEnum));
    210                                         count++;
    211                                 }
    212                                 xDelete<IssmDouble>(values);
     409                        else{
     410                                basalmeltingrates[vertexdown]=meltingrate_enthalpy[is];
     411                                watercolumns[vertexdown]+=dt*meltingrate_enthalpy[is];
    213412                        }
    214413                }
    215         }
    216         else{
    217                 _error_("Size of field " << EnumToStringx(ThermalSpctemperatureEnum) << " not supported");
    218         }
    219 
    220         /*Free ressources:*/
    221         iomodel->DeleteData(spcvector,ThermalSpctemperatureEnum);
    222         xDelete<IssmDouble>(times);
    223         xDelete<IssmDouble>(values);
    224 }/*}}}*/
    225 void EnthalpyAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
    226 
    227         /*No loads */
    228 }/*}}}*/
    229 
    230 /*Finite Element Analysis*/
    231 void EnthalpyAnalysis::Core(FemModel* femmodel){/*{{{*/
     414                else{
     415                        basalmeltingrates[vertexdown]=meltingrate_enthalpy[is];
     416                        if(watercolumns[vertexdown]+meltingrate_enthalpy[is]<0.)
     417                                watercolumns[vertexdown]=0.;
     418                        else
     419                                watercolumns[vertexdown]+=meltingrate_enthalpy[is];
     420                }       
     421                basalmeltingrates[vertexdown]*=rho_water/rho_ice; // convert meltingrate from water to ice equivalent
     422                _assert_(watercolumns[vertexdown]>=0.);
     423        }/*}}}*/
     424
     425        /*feed updated variables back into model*/
     426        if(dt!=0.){
     427                element->AddInput(enthalpy_enum,enthalpies,P1Enum); //TODO: distinguis for steadystate and transient run
     428                element->AddInput(WatercolumnEnum,watercolumns,P1Enum);
     429        }
     430        element->AddInput(BasalforcingsGroundediceMeltingRateEnum,basalmeltingrates,P1Enum);
     431
     432        /*Clean up and return*/
     433        delete gauss;
     434        delete friction;
     435        xDelete<int>(pairindices);
     436        xDelete<IssmDouble>(enthalpies);
     437        xDelete<IssmDouble>(pressures);
     438        xDelete<IssmDouble>(watercolumns);
     439        xDelete<IssmDouble>(basalmeltingrates);
     440        xDelete<IssmDouble>(meltingrate_enthalpy);
     441        xDelete<IssmDouble>(heating);
     442        xDelete<IssmDouble>(xyz_list);
     443        xDelete<IssmDouble>(xyz_list_base);
     444}/*}}}*/
     445void           EnthalpyAnalysis::Core(FemModel* femmodel){/*{{{*/
    232446        if(VerboseSolution()) _printf0_("   computing enthalpy\n");
    233447        femmodel->SetCurrentConfiguration(EnthalpyAnalysisEnum);
     
    741955        return pe;
    742956}/*}}}*/
    743 void EnthalpyAnalysis::GetBConduct(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
    744         /*Compute B  matrix. B=[B1 B2 B3 B4 B5 B6] where Bi is of size 5*NDOF1.
    745          * For node i, Bi' can be expressed in the actual coordinate system
    746          * by:
    747          *       Bi_conduct=[ dh/dx ]
    748          *                  [ dh/dy ]
    749          *                  [ dh/dz ]
    750          * where h is the interpolation function for node i.
    751          *
    752          * We assume B has been allocated already, of size: 3x(NDOF1*numnodes)
    753          */
    754 
    755         /*Fetch number of nodes for this finite element*/
    756         int numnodes = element->GetNumberOfNodes();
    757 
    758         /*Get nodal functions derivatives*/
    759         IssmDouble* dbasis=xNew<IssmDouble>(3*numnodes);
    760         element->NodalFunctionsDerivatives(dbasis,xyz_list,gauss);
    761 
    762         /*Build B: */
    763         for(int i=0;i<numnodes;i++){
    764                 B[numnodes*0+i] = dbasis[0*numnodes+i];
    765                 B[numnodes*1+i] = dbasis[1*numnodes+i];
    766                 B[numnodes*2+i] = dbasis[2*numnodes+i];
    767         }
    768 
    769         /*Clean-up*/
    770         xDelete<IssmDouble>(dbasis);
    771 }/*}}}*/
    772 void EnthalpyAnalysis::GetBAdvec(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
    773         /*Compute B  matrix. B=[B1 B2 B3 B4 B5 B6] where Bi is of size 5*NDOF1.
    774          * For node i, Bi' can be expressed in the actual coordinate system
    775          * by:
    776          *       Bi_advec =[ h ]
    777          *                 [ h ]
    778          *                 [ h ]
    779          * where h is the interpolation function for node i.
    780          *
    781          * We assume B has been allocated already, of size: 3x(NDOF1*NUMNODESP1)
    782          */
    783 
    784         /*Fetch number of nodes for this finite element*/
    785         int numnodes = element->GetNumberOfNodes();
    786 
    787         /*Get nodal functions*/
    788         IssmDouble* basis=xNew<IssmDouble>(numnodes);
    789         element->NodalFunctions(basis,gauss);
    790 
    791         /*Build B: */
    792         for(int i=0;i<numnodes;i++){
    793                 B[numnodes*0+i] = basis[i];
    794                 B[numnodes*1+i] = basis[i];
    795                 B[numnodes*2+i] = basis[i];
    796         }
    797 
    798         /*Clean-up*/
    799         xDelete<IssmDouble>(basis);
    800 }/*}}}*/
    801 void EnthalpyAnalysis::GetBAdvecprime(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
    802         /*Compute B  matrix. B=[B1 B2 B3 B4 B5 B6] where Bi is of size 5*NDOF1.
    803          * For node i, Bi' can be expressed in the actual coordinate system
    804          * by:
    805          *       Biprime_advec=[ dh/dx ]
    806          *                     [ dh/dy ]
    807          *                     [ dh/dz ]
    808          * where h is the interpolation function for node i.
    809          *
    810          * We assume B has been allocated already, of size: 3x(NDOF1*numnodes)
    811          */
    812 
    813         /*Fetch number of nodes for this finite element*/
    814         int numnodes = element->GetNumberOfNodes();
    815 
    816         /*Get nodal functions derivatives*/
    817         IssmDouble* dbasis=xNew<IssmDouble>(3*numnodes);
    818         element->NodalFunctionsDerivatives(dbasis,xyz_list,gauss);
    819 
    820         /*Build B: */
    821         for(int i=0;i<numnodes;i++){
    822                 B[numnodes*0+i] = dbasis[0*numnodes+i];
    823                 B[numnodes*1+i] = dbasis[1*numnodes+i];
    824                 B[numnodes*2+i] = dbasis[2*numnodes+i];
    825         }
    826 
    827         /*Clean-up*/
    828         xDelete<IssmDouble>(dbasis);
    829 }/*}}}*/
    830 void EnthalpyAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
    831         element->GetSolutionFromInputsOneDof(solution,EnthalpyEnum);
    832 }/*}}}*/
    833 void EnthalpyAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
    834         _error_("Not implemented yet");
    835 }/*}}}*/
    836 void EnthalpyAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
    837 
    838         bool        converged;
    839         int         i,rheology_law;
    840         IssmDouble  B_average,s_average,T_average=0.,P_average=0.;
    841         int        *doflist   = NULL;
    842         IssmDouble *xyz_list  = NULL;
    843 
    844         /*Fetch number of nodes and dof for this finite element*/
    845         int numnodes    = element->GetNumberOfNodes();
    846 
    847         /*Fetch dof list and allocate solution vector*/
    848         element->GetDofList(&doflist,NoneApproximationEnum,GsetEnum);
    849         IssmDouble* values        = xNew<IssmDouble>(numnodes);
    850         IssmDouble* pressure      = xNew<IssmDouble>(numnodes);
    851         IssmDouble* surface       = xNew<IssmDouble>(numnodes);
    852         IssmDouble* B             = xNew<IssmDouble>(numnodes);
    853         IssmDouble* temperature   = xNew<IssmDouble>(numnodes);
    854         IssmDouble* waterfraction = xNew<IssmDouble>(numnodes);
    855 
    856         /*Use the dof list to index into the solution vector: */
    857         for(i=0;i<numnodes;i++){
    858                 values[i]=solution[doflist[i]];
    859 
    860                 /*Check solution*/
    861                 if(xIsNan<IssmDouble>(values[i])) _error_("NaN found in solution vector");
    862         }
    863 
    864         /*Get all inputs and parameters*/
    865         element->GetInputValue(&converged,ConvergedEnum);
    866         element->GetInputListOnNodes(&pressure[0],PressureEnum);
    867         if(converged){
    868                 for(i=0;i<numnodes;i++){
    869                         element->EnthalpyToThermal(&temperature[i],&waterfraction[i],values[i],pressure[i]);
    870                         if(waterfraction[i]<0.) _error_("Negative water fraction found in solution vector");
    871                         //if(waterfraction[i]>1.) _error_("Water fraction >1 found in solution vector");
    872                 }
    873                 element->AddInput(EnthalpyEnum,values,element->GetElementType());
    874                 element->AddInput(WaterfractionEnum,waterfraction,element->GetElementType());
    875                 element->AddInput(TemperatureEnum,temperature,element->GetElementType());
    876 
    877                 /*Update Rheology only if converged (we must make sure that the temperature is below melting point
    878                  * otherwise the rheology could be negative*/
    879                 element->FindParam(&rheology_law,MaterialsRheologyLawEnum);
    880                 element->GetInputListOnNodes(&surface[0],SurfaceEnum);
    881                 switch(rheology_law){
    882                         case NoneEnum:
    883                                 /*Do nothing: B is not temperature dependent*/
    884                                 break;
    885                         case CuffeyEnum:
    886                                 for(i=0;i<numnodes;i++) B[i]=Cuffey(temperature[i]);
    887                                 element->AddInput(MaterialsRheologyBEnum,&B[0],element->GetElementType());
    888                                 break;
    889                         case PatersonEnum:
    890                                 for(i=0;i<numnodes;i++) B[i]=Paterson(temperature[i]);
    891                                 element->AddInput(MaterialsRheologyBEnum,&B[0],element->GetElementType());
    892                                 break;
    893                         case ArrheniusEnum:
    894                                 element->GetVerticesCoordinates(&xyz_list);
    895                                 for(i=0;i<numnodes;i++) B[i]=Arrhenius(temperature[i],surface[i]-xyz_list[i*3+2],element->GetMaterialParameter(MaterialsRheologyNEnum));
    896                                 element->AddInput(MaterialsRheologyBEnum,&B[0],element->GetElementType());
    897                                 break;
    898                         case LliboutryDuvalEnum:
    899                                 for(i=0;i<numnodes;i++) B[i]=LliboutryDuval(values[i],pressure[i],element->GetMaterialParameter(MaterialsRheologyNEnum),element->GetMaterialParameter(MaterialsBetaEnum),element->GetMaterialParameter(ConstantsReferencetemperatureEnum),element->GetMaterialParameter(MaterialsHeatcapacityEnum),element->GetMaterialParameter(MaterialsLatentheatEnum));
    900                                 element->AddInput(MaterialsRheologyBEnum,&B[0],element->GetElementType());
    901                                 break;
    902                         default: _error_("Rheology law " << EnumToStringx(rheology_law) << " not supported yet");
    903                 }
    904         }
    905         else{
    906                 element->AddInput(EnthalpyPicardEnum,values,element->GetElementType());
    907         }
    908 
    909         /*Free ressources:*/
    910         xDelete<IssmDouble>(values);
    911         xDelete<IssmDouble>(pressure);
    912         xDelete<IssmDouble>(surface);
    913         xDelete<IssmDouble>(B);
    914         xDelete<IssmDouble>(temperature);
    915         xDelete<IssmDouble>(waterfraction);
    916         xDelete<IssmDouble>(xyz_list);
    917         xDelete<int>(doflist);
    918 }/*}}}*/
    919 void EnthalpyAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
    920 
    921         bool islevelset;
    922         femmodel->parameters->FindParam(&islevelset,TransientIslevelsetEnum);
    923         if(islevelset){
    924                 SetActiveNodesLSMx(femmodel);
    925         }
    926         return;
    927 }/*}}}*/
    928 
    929 /*Modules*/
    930 void EnthalpyAnalysis::PostProcessing(FemModel* femmodel){/*{{{*/
    931 
    932         /*Intermediaries*/
    933         bool computebasalmeltingrates=true;
    934         bool drainicecolumn=true;
    935         bool isdynamicbasalspc;
    936         IssmDouble dt;
    937 
    938         femmodel->parameters->FindParam(&isdynamicbasalspc,ThermalIsdynamicbasalspcEnum);
    939         femmodel->parameters->FindParam(&dt,TimesteppingTimeStepEnum);
    940 
    941         //TODO: use dt to decide what to do
    942         if(drainicecolumn)      DrainWaterfraction(femmodel);
    943         if(computebasalmeltingrates)    ComputeBasalMeltingrate(femmodel);
    944         if(isdynamicbasalspc)   UpdateBasalConstraints(femmodel);
    945 
    946 }/*}}}*/
    947 void EnthalpyAnalysis::ComputeBasalMeltingrate(FemModel* femmodel){/*{{{*/
    948         /*Compute basal melting rates: */
    949         for(int i=0;i<femmodel->elements->Size();i++){
    950                 Element* element=xDynamicCast<Element*>(femmodel->elements->GetObjectByOffset(i));
    951                 ComputeBasalMeltingrate(element);
    952         }
    953 }/*}}}*/
    954 void EnthalpyAnalysis::ComputeBasalMeltingrate(Element* element){/*{{{*/
    955         /*Calculate the basal melt rates of the enthalpy model after Aschwanden 2012*/
    956         /* melting rate is positive when melting, negative when refreezing*/
    957 
    958         /* Check if ice in element */
    959         if(!element->IsIceInElement()) return;
    960 
    961         /* Only compute melt rates at the base of grounded ice*/
    962         if(!element->IsOnBase() || element->IsFloating()) return;
    963 
    964         /* Intermediaries */
    965         bool                    converged;
    966         const int   dim=3;
    967         int         i,is,state;
    968         int                     vertexdown,vertexup,numvertices,numsegments;
    969         int                     enthalpy_enum;
    970         IssmDouble  vec_heatflux[dim],normal_base[dim],d1enthalpy[dim],d1pressure[dim];
    971         IssmDouble  basalfriction,alpha2,geothermalflux,heatflux;
    972         IssmDouble  dt,yts;
    973         IssmDouble  melting_overshoot,lambda;
    974         IssmDouble  vx,vy,vz;
    975         IssmDouble *xyz_list      = NULL;
    976         IssmDouble *xyz_list_base = NULL;
    977         int        *pairindices   = NULL;
    978 
    979         /*Fetch parameters*/
    980         element->GetVerticesCoordinates(&xyz_list);
    981         element->GetVerticesCoordinatesBase(&xyz_list_base);
    982         element->GetInputValue(&converged,ConvergedEnum);
    983         element->FindParam(&dt,TimesteppingTimeStepEnum);
    984         element->FindParam(&yts, ConstantsYtsEnum);
    985 
    986         if(dt==0. && !converged) enthalpy_enum=EnthalpyPicardEnum;
    987         else enthalpy_enum=EnthalpyEnum;
    988 
    989         IssmDouble latentheat = element->GetMaterialParameter(MaterialsLatentheatEnum);
    990         IssmDouble rho_ice    = element->GetMaterialParameter(MaterialsRhoIceEnum);
    991         IssmDouble rho_water  = element->GetMaterialParameter(MaterialsRhoFreshwaterEnum);
    992         IssmDouble beta          = element->GetMaterialParameter(MaterialsBetaEnum);
    993         IssmDouble kappa                 = EnthalpyDiffusionParameterVolume(element,enthalpy_enum);     _assert_(kappa>=0.);
    994         IssmDouble kappa_mix;
    995 
    996         /*retrieve inputs*/
    997         Input* enthalpy_input         = element->GetInput(enthalpy_enum);                    _assert_(enthalpy_input);
    998         Input* pressure_input                   = element->GetInput(PressureEnum);                                                       _assert_(pressure_input);
    999         Input* geothermalflux_input   = element->GetInput(BasalforcingsGeothermalfluxEnum); _assert_(geothermalflux_input);
    1000         Input* vx_input               = element->GetInput(VxEnum);                          _assert_(vx_input);
    1001         Input* vy_input               = element->GetInput(VyEnum);                          _assert_(vy_input);
    1002         Input* vz_input               = element->GetInput(VzEnum);                          _assert_(vz_input);
    1003 
    1004         /*Build friction element, needed later: */
    1005         Friction* friction=new Friction(element,dim);
    1006 
    1007         /******** MELTING RATES  ************************************//*{{{*/
    1008         element->NormalBase(&normal_base[0],xyz_list_base);
    1009         element->VerticalSegmentIndices(&pairindices,&numsegments);
    1010         IssmDouble* meltingrate_enthalpy = xNew<IssmDouble>(numsegments);
    1011         IssmDouble* heating = xNew<IssmDouble>(numsegments);   
    1012 
    1013         numvertices=element->GetNumberOfVertices();
    1014         IssmDouble* enthalpies = xNew<IssmDouble>(numvertices);
    1015         IssmDouble* pressures = xNew<IssmDouble>(numvertices);
    1016         IssmDouble* watercolumns = xNew<IssmDouble>(numvertices);
    1017         IssmDouble* basalmeltingrates = xNew<IssmDouble>(numvertices);
    1018         element->GetInputListOnVertices(enthalpies,enthalpy_enum);
    1019         element->GetInputListOnVertices(pressures,PressureEnum);
    1020         element->GetInputListOnVertices(watercolumns,WatercolumnEnum);
    1021         element->GetInputListOnVertices(basalmeltingrates,BasalforcingsGroundediceMeltingRateEnum);
    1022 
    1023         Gauss* gauss=element->NewGauss();
    1024         for(is=0;is<numsegments;is++){
    1025                 vertexdown = pairindices[is*2+0];
    1026                 vertexup   = pairindices[is*2+1];
    1027                 gauss->GaussVertex(vertexdown);
    1028 
    1029                 state=GetThermalBasalCondition(element, enthalpies[vertexdown], enthalpies[vertexup], pressures[vertexdown], pressures[vertexup], watercolumns[vertexdown], basalmeltingrates[vertexdown]);
    1030                 switch (state) {
    1031                         case 0:
    1032                                 // cold, dry base: apply basal surface forcing
    1033                                 for(i=0;i<3;i++) vec_heatflux[i]=0.;
    1034                                 break;
    1035                         case 1: case 2: case 3:
    1036                                 // case 1 : cold, wet base: keep at pressure melting point
    1037                                 // case 2: temperate, thin refreezing base: release spc
    1038                                 // case 3: temperate, thin melting base: set spc
    1039                                 enthalpy_input->GetInputDerivativeValue(&d1enthalpy[0],xyz_list,gauss);
    1040                                 for(i=0;i<3;i++) vec_heatflux[i]=-kappa*d1enthalpy[i];
    1041                                 break;
    1042                         case 4:
    1043                                 // temperate, thick melting base: set grad H*n=0
    1044                                 kappa_mix=GetWetIceConductivity(element, enthalpies[vertexdown], pressures[vertexdown]);
    1045                                 pressure_input->GetInputDerivativeValue(&d1pressure[0],xyz_list,gauss);
    1046                                 for(i=0;i<3;i++) vec_heatflux[i]=kappa_mix*beta*d1pressure[i];
    1047                                 break;
    1048                         default:
    1049                                 _printf0_("     unknown thermal basal state found!");
    1050                 }
    1051                 if(state==0) meltingrate_enthalpy[is]=0.;
    1052                 else{
    1053                         /*heat flux along normal*/
    1054                         heatflux=0.;
    1055                         for(i=0;i<3;i++) heatflux+=(vec_heatflux[i])*normal_base[i];
    1056 
    1057                         /*basal friction*/
    1058                         friction->GetAlpha2(&alpha2,gauss);
    1059                         vx_input->GetInputValue(&vx,gauss);             vy_input->GetInputValue(&vy,gauss);             vz_input->GetInputValue(&vz,gauss);
    1060                         basalfriction=alpha2*(vx*vx + vy*vy + vz*vz);
    1061                         geothermalflux_input->GetInputValue(&geothermalflux,gauss);
    1062                         /* -Mb= Fb-(q-q_geo)/((1-w)*L*rho), and (1-w)*rho=rho_ice, cf Aschwanden 2012, eqs.1, 2, 66*/
    1063                         heating[is]=(heatflux+basalfriction+geothermalflux);
    1064                         meltingrate_enthalpy[is]=heating[is]/(latentheat*rho_ice); // m/s water equivalent
    1065                 }
    1066         }/*}}}*/
    1067 
    1068         /******** UPDATE MELTINGRATES AND WATERCOLUMN **************//*{{{*/
    1069         for(is=0;is<numsegments;is++){
    1070                 vertexdown = pairindices[is*2+0];
    1071                 vertexup   = pairindices[is*2+1];
    1072                 if(dt!=0.){
    1073                         if(watercolumns[vertexdown]+meltingrate_enthalpy[is]*dt<0.){    // prevent too much freeze on                   
    1074                                 lambda = -watercolumns[vertexdown]/(dt*meltingrate_enthalpy[is]); _assert_(lambda>=0.); _assert_(lambda<1.);
    1075                                 watercolumns[vertexdown]=0.;
    1076                                 basalmeltingrates[vertexdown]=lambda*meltingrate_enthalpy[is]; // restrict freeze on only to size of watercolumn
    1077                                 enthalpies[vertexdown]+=(1.-lambda)*dt/yts*meltingrate_enthalpy[is]*latentheat*rho_ice; // use rest of energy to cool down base: dE=L*m, m=(1-lambda)*meltingrate*rho_ice
    1078                         }
    1079                         else{
    1080                                 basalmeltingrates[vertexdown]=meltingrate_enthalpy[is];
    1081                                 watercolumns[vertexdown]+=dt*meltingrate_enthalpy[is];
    1082                         }
    1083                 }
    1084                 else{
    1085                         basalmeltingrates[vertexdown]=meltingrate_enthalpy[is];
    1086                         if(watercolumns[vertexdown]+meltingrate_enthalpy[is]<0.)
    1087                                 watercolumns[vertexdown]=0.;
    1088                         else
    1089                                 watercolumns[vertexdown]+=meltingrate_enthalpy[is];
    1090                 }       
    1091                 basalmeltingrates[vertexdown]*=rho_water/rho_ice; // convert meltingrate from water to ice equivalent
    1092                 _assert_(watercolumns[vertexdown]>=0.);
    1093         }/*}}}*/
    1094 
    1095         /*feed updated variables back into model*/
    1096         if(dt!=0.){
    1097                 element->AddInput(enthalpy_enum,enthalpies,P1Enum); //TODO: distinguis for steadystate and transient run
    1098                 element->AddInput(WatercolumnEnum,watercolumns,P1Enum);
    1099         }
    1100         element->AddInput(BasalforcingsGroundediceMeltingRateEnum,basalmeltingrates,P1Enum);
    1101 
    1102         /*Clean up and return*/
    1103         delete gauss;
    1104         delete friction;
    1105         xDelete<int>(pairindices);
    1106         xDelete<IssmDouble>(enthalpies);
    1107         xDelete<IssmDouble>(pressures);
    1108         xDelete<IssmDouble>(watercolumns);
    1109         xDelete<IssmDouble>(basalmeltingrates);
    1110         xDelete<IssmDouble>(meltingrate_enthalpy);
    1111         xDelete<IssmDouble>(heating);
    1112         xDelete<IssmDouble>(xyz_list);
    1113         xDelete<IssmDouble>(xyz_list_base);
    1114 }/*}}}*/
    1115 void EnthalpyAnalysis::DrainWaterfraction(FemModel* femmodel){/*{{{*/
     957void           EnthalpyAnalysis::DrainWaterfraction(FemModel* femmodel){/*{{{*/
    1116958        /*Drain excess water fraction in ice column: */
    1117959        for(int i=0;i<femmodel->elements->Size();i++){
     
    1120962        }
    1121963}/*}}}*/
    1122 void EnthalpyAnalysis::DrainWaterfractionIcecolumn(Element* element){/*{{{*/
    1123 
    1124         /* Check if ice in element */
    1125         if(!element->IsIceInElement()) return;
    1126 
    1127         /* Only drain waterfraction of ice column from element at base*/
    1128         if(!element->IsOnBase()) return; //FIXME: allow freeze on for floating elements
    1129 
    1130         /* Intermediaries*/
    1131         int is, numvertices, numsegments;
    1132         int *pairindices   = NULL;
    1133 
    1134         numvertices=element->GetNumberOfVertices();
    1135         element->VerticalSegmentIndices(&pairindices,&numsegments);
    1136 
    1137         IssmDouble* watercolumn = xNew<IssmDouble>(numvertices);
    1138         IssmDouble* drainrate_column  = xNew<IssmDouble>(numsegments);
    1139         IssmDouble* drainrate_element = xNew<IssmDouble>(numsegments);
    1140 
    1141         element->GetInputListOnVertices(watercolumn,WatercolumnEnum);
    1142 
    1143         for(is=0;is<numsegments;is++)   drainrate_column[is]=0.;
    1144         Element* elementi = element;
    1145         for(;;){
    1146                 for(is=0;is<numsegments;is++)   drainrate_element[is]=0.;
    1147                 DrainWaterfraction(elementi,drainrate_element); // TODO: make sure every vertex is only drained once
    1148                 for(is=0;is<numsegments;is++)   drainrate_column[is]+=drainrate_element[is];
    1149 
    1150                 if(elementi->IsOnSurface()) break;
    1151                 elementi=elementi->GetUpperElement();                   
    1152         }
    1153         /* add drained water to water column*/
    1154         for(is=0;is<numsegments;is++) watercolumn[is]+=drainrate_column[is];
    1155         /* Feed updated water column back into model */
    1156         element->AddInput(WatercolumnEnum,watercolumn,P1Enum);
    1157 
    1158         xDelete<int>(pairindices);
    1159         xDelete<IssmDouble>(drainrate_column);
    1160         xDelete<IssmDouble>(drainrate_element);
    1161         xDelete<IssmDouble>(watercolumn);
    1162 }/*}}}*/
    1163 void EnthalpyAnalysis::DrainWaterfraction(Element* element, IssmDouble* pdrainrate_element){/*{{{*/
     964void           EnthalpyAnalysis::DrainWaterfraction(Element* element, IssmDouble* pdrainrate_element){/*{{{*/
    1164965
    1165966        /* Check if ice in element */
     
    12231024        xDelete<IssmDouble>(deltawaterfractions);
    12241025}/*}}}*/
    1225 void EnthalpyAnalysis::UpdateBasalConstraints(FemModel* femmodel){/*{{{*/
    1226 
    1227         /*Update basal dirichlet BCs for enthalpy: */
    1228         Vector<IssmDouble>* spc           = NULL;
    1229         IssmDouble*         serial_spc    = NULL;
    1230 
    1231         spc=new Vector<IssmDouble>(femmodel->nodes->NumberOfNodes(EnthalpyAnalysisEnum));
    1232         /*First create a vector to figure out what elements should be constrained*/
    1233         for(int i=0;i<femmodel->elements->Size();i++){
    1234                 Element* element=xDynamicCast<Element*>(femmodel->elements->GetObjectByOffset(i));
    1235                 GetBasalConstraints(spc,element);
    1236         }
    1237 
    1238         /*Assemble and serialize*/
    1239         spc->Assemble();
    1240         serial_spc=spc->ToMPISerial();
    1241         delete spc;
    1242 
    1243         /*Then update basal constraints nodes accordingly*/
    1244         for(int i=0;i<femmodel->elements->Size();i++){
    1245                 Element* element=xDynamicCast<Element*>(femmodel->elements->GetObjectByOffset(i));
    1246                 ApplyBasalConstraints(serial_spc,element);
    1247         }
    1248 
    1249         femmodel->UpdateConstraintsx();
    1250 
    1251         /*Delete*/
    1252         xDelete<IssmDouble>(serial_spc);
    1253 }/*}}}*/
    1254 void EnthalpyAnalysis::ApplyBasalConstraints(IssmDouble* serial_spc,Element* element){/*{{{*/
     1026void           EnthalpyAnalysis::DrainWaterfractionIcecolumn(Element* element){/*{{{*/
    12551027
    12561028        /* Check if ice in element */
    12571029        if(!element->IsIceInElement()) return;
    12581030
    1259         /* Only update Constraints at the base of grounded ice*/
    1260         if(!(element->IsOnBase()) || element->IsFloating()) return;
    1261 
    1262         /*Intermediary*/
    1263         bool        isdynamicbasalspc;
    1264         int         numindices;
    1265         int        *indices = NULL;
    1266         Node*       node = NULL;
    1267         IssmDouble      pressure;
    1268 
    1269         /*Check wether dynamic basal boundary conditions are activated */
    1270         element->FindParam(&isdynamicbasalspc,ThermalIsdynamicbasalspcEnum);
    1271         if(!isdynamicbasalspc) return;
    1272 
    1273         /*Get parameters and inputs: */
    1274         Input* pressure_input            = element->GetInput(PressureEnum);                                                      _assert_(pressure_input);
    1275 
    1276         /*Fetch indices of basal & surface nodes for this finite element*/
    1277         Penta *penta =  (Penta *) element; // TODO: add Basal-/SurfaceNodeIndices to element.h, and change this to Element*
    1278         penta->BasalNodeIndices(&numindices,&indices,element->GetElementType());
    1279 
    1280         GaussPenta* gauss=new GaussPenta();
    1281         for(int i=0;i<numindices;i++){
    1282                 gauss->GaussNode(element->GetElementType(),indices[i]);
    1283 
    1284                 pressure_input->GetInputValue(&pressure,gauss);
    1285 
    1286                 /*apply or release spc*/
    1287                 node=element->GetNode(indices[i]);
    1288                 if(serial_spc[node->Sid()]==1.){
    1289                         pressure_input->GetInputValue(&pressure, gauss);
    1290                         node->ApplyConstraint(0,PureIceEnthalpy(element,pressure));
    1291                 }
    1292                 else                   
    1293                         node->DofInFSet(0);
    1294         }
    1295 
    1296         /*Free ressources:*/
    1297         xDelete<int>(indices);
    1298         delete gauss;
    1299 }/*}}}*/
    1300 void EnthalpyAnalysis::GetBasalConstraints(Vector<IssmDouble>* vec_spc,Element* element){/*{{{*/
    1301 
    1302         /* Check if ice in element */
    1303         if(!element->IsIceInElement()) return;
    1304 
    1305         /* Only update Constraints at the base of grounded ice*/
    1306         if(!(element->IsOnBase()) || element->IsFloating()) return;
    1307 
    1308         /*Intermediary*/
    1309         bool        isdynamicbasalspc;
    1310         IssmDouble      dt;
    1311 
    1312         /*Check wether dynamic basal boundary conditions are activated */
    1313         element->FindParam(&isdynamicbasalspc,ThermalIsdynamicbasalspcEnum);
    1314         if(!isdynamicbasalspc) return;
    1315 
    1316         element->FindParam(&dt,TimesteppingTimeStepEnum);
    1317         if(dt==0.){
    1318                 GetBasalConstraintsSteadystate(vec_spc,element);
    1319         }
    1320         else{
    1321                 GetBasalConstraintsTransient(vec_spc,element);
    1322         }
    1323 }/*}}}*/
    1324 void EnthalpyAnalysis::GetBasalConstraintsTransient(Vector<IssmDouble>* vec_spc,Element* element){/*{{{*/
    1325 
    1326         /* Check if ice in element */
    1327         if(!element->IsIceInElement()) return;
    1328 
    1329         /* Only update Constraints at the base of grounded ice*/
    1330         if(!(element->IsOnBase()) || element->IsFloating()) return;
    1331 
    1332         /*Intermediary*/
    1333         int         numindices, numindicesup, state;
    1334         int        *indices = NULL, *indicesup = NULL;
    1335         IssmDouble      enthalpy, enthalpyup, pressure, pressureup, watercolumn, meltingrate;
    1336 
    1337         /*Get parameters and inputs: */
    1338         Input* enthalpy_input       = element->GetInput(EnthalpyEnum);                    _assert_(enthalpy_input); //TODO: check EnthalpyPicard?
    1339         Input* pressure_input            = element->GetInput(PressureEnum);                                                      _assert_(pressure_input);
    1340         Input* watercolumn_input         = element->GetInput(WatercolumnEnum);                                                   _assert_(watercolumn_input);
    1341         Input* meltingrate_input         = element->GetInput(BasalforcingsGroundediceMeltingRateEnum);                                                   _assert_(meltingrate_input);
    1342 
    1343         /*Fetch indices of basal & surface nodes for this finite element*/
    1344         Penta *penta =  (Penta *) element; // TODO: add Basal-/SurfaceNodeIndices to element.h, and change this to Element*
    1345         penta->BasalNodeIndices(&numindices,&indices,element->GetElementType());
    1346         penta->SurfaceNodeIndices(&numindicesup,&indicesup,element->GetElementType());  _assert_(numindices==numindicesup);
    1347 
    1348         GaussPenta* gauss=new GaussPenta();
    1349         GaussPenta* gaussup=new GaussPenta();
    1350 
    1351         for(int i=0;i<numindices;i++){
    1352                 gauss->GaussNode(element->GetElementType(),indices[i]);
    1353                 gaussup->GaussNode(element->GetElementType(),indicesup[i]);
    1354                
    1355                 enthalpy_input->GetInputValue(&enthalpy,gauss);
    1356                 enthalpy_input->GetInputValue(&enthalpyup,gaussup);
    1357                 pressure_input->GetInputValue(&pressure,gauss);
    1358                 pressure_input->GetInputValue(&pressureup,gaussup);
    1359                 watercolumn_input->GetInputValue(&watercolumn,gauss);
    1360                 meltingrate_input->GetInputValue(&meltingrate,gauss);
    1361 
    1362                 state=GetThermalBasalCondition(element, enthalpy, enthalpyup, pressure, pressureup, watercolumn, meltingrate);
    1363 
    1364                 switch (state) {
    1365                         case 0:
    1366                                 // cold, dry base: apply basal surface forcing
    1367                                 vec_spc->SetValue(element->nodes[i]->Sid(),0.,INS_VAL);
    1368                                 break;
    1369                         case 1:
    1370                                 // cold, wet base: keep at pressure melting point
    1371                                 vec_spc->SetValue(element->nodes[i]->Sid(),1.,INS_VAL);
    1372                                 break;
    1373                         case 2:
    1374                                 // temperate, thin refreezing base: release spc
    1375                                 vec_spc->SetValue(element->nodes[i]->Sid(),0.,INS_VAL);
    1376                                 break;
    1377                         case 3:
    1378                                 // temperate, thin melting base: set spc
    1379                                 vec_spc->SetValue(element->nodes[i]->Sid(),1.,INS_VAL);
    1380                                 break;
    1381                         case 4:
    1382                                 // temperate, thick melting base: set grad H*n=0
    1383                                 vec_spc->SetValue(element->nodes[i]->Sid(),0.,INS_VAL);
    1384                                 break;
    1385                         default:
    1386                                 _printf0_("     unknown thermal basal state found!");
    1387                 }
    1388 
    1389         }
    1390 
    1391         /*Free ressources:*/
    1392         xDelete<int>(indices);
    1393         xDelete<int>(indicesup);
    1394         delete gauss;
    1395         delete gaussup;
    1396 }/*}}}*/
    1397 void EnthalpyAnalysis::GetBasalConstraintsSteadystate(Vector<IssmDouble>* vec_spc,Element* element){/*{{{*/
    1398 
    1399         /* Check if ice in element */
    1400         if(!element->IsIceInElement()) return;
    1401 
    1402         /* Only update Constraints at the base of grounded ice*/
    1403         if(!(element->IsOnBase()) || element->IsFloating()) return;
    1404 
    1405         /*Intermediary*/
    1406         int         numindices, numindicesup, state;
    1407         int        *indices = NULL, *indicesup = NULL;
    1408         IssmDouble      enthalpy, enthalpyup, pressure, pressureup, watercolumn, meltingrate;
    1409 
    1410         /*Get parameters and inputs: */
    1411         Input* enthalpy_input            = element->GetInput(EnthalpyPicardEnum);                                        _assert_(enthalpy_input);
    1412         Input* pressure_input            = element->GetInput(PressureEnum);                                                      _assert_(pressure_input);
    1413         Input* watercolumn_input         = element->GetInput(WatercolumnEnum);                                                   _assert_(watercolumn_input);
    1414         Input* meltingrate_input         = element->GetInput(BasalforcingsGroundediceMeltingRateEnum);                                                   _assert_(meltingrate_input);
    1415 
    1416         /*Fetch indices of basal & surface nodes for this finite element*/
    1417         Penta *penta =  (Penta *) element; // TODO: add Basal-/SurfaceNodeIndices to element.h, and change this to Element*
    1418         penta->BasalNodeIndices(&numindices,&indices,element->GetElementType());
    1419         penta->SurfaceNodeIndices(&numindicesup,&indicesup,element->GetElementType());  _assert_(numindices==numindicesup);
    1420 
    1421         GaussPenta* gauss=new GaussPenta();
    1422         GaussPenta* gaussup=new GaussPenta();
    1423         for(int i=0;i<numindices;i++){
    1424                 gauss->GaussNode(element->GetElementType(),indices[i]);
    1425                 gaussup->GaussNode(element->GetElementType(),indicesup[i]);
    1426 
    1427                 enthalpy_input->GetInputValue(&enthalpy,gauss);
    1428                 enthalpy_input->GetInputValue(&enthalpyup,gaussup);
    1429                 pressure_input->GetInputValue(&pressure,gauss);
    1430                 pressure_input->GetInputValue(&pressureup,gaussup);
    1431                 watercolumn_input->GetInputValue(&watercolumn,gauss);
    1432                 meltingrate_input->GetInputValue(&meltingrate,gauss);
    1433 
    1434                 state=GetThermalBasalCondition(element, enthalpy, enthalpyup, pressure, pressureup, watercolumn, meltingrate);
    1435                 switch (state) {
    1436                         case 0:
    1437                                 // cold, dry base: apply basal surface forcing
    1438                                 vec_spc->SetValue(element->nodes[i]->Sid(),0.,INS_VAL);
    1439                                 break;
    1440                         case 1:
    1441                                 // cold, wet base: keep at pressure melting point
    1442                                 vec_spc->SetValue(element->nodes[i]->Sid(),1.,INS_VAL);
    1443                                 break;
    1444                         case 2:
    1445                                 // temperate, thin refreezing base: release spc
    1446                                 vec_spc->SetValue(element->nodes[i]->Sid(),0.,INS_VAL);
    1447                                 break;
    1448                         case 3:
    1449                                 // temperate, thin melting base: set spc
    1450                                 vec_spc->SetValue(element->nodes[i]->Sid(),1.,INS_VAL);
    1451                                 break;
    1452                         case 4:
    1453                                 // temperate, thick melting base: s
    1454                                 vec_spc->SetValue(element->nodes[i]->Sid(),1.,INS_VAL);
    1455                                 break;
    1456                         default:
    1457                                 _printf0_("     unknown thermal basal state found!");
    1458                 }
    1459         }
    1460 
    1461         /*Free ressources:*/
    1462         xDelete<int>(indices);
    1463         xDelete<int>(indicesup);
    1464         delete gauss;
    1465         delete gaussup;
    1466 }/*}}}*/
    1467 int EnthalpyAnalysis::GetThermalBasalCondition(Element* element, IssmDouble enthalpy, IssmDouble enthalpyup, IssmDouble pressure, IssmDouble pressureup, IssmDouble watercolumn, IssmDouble meltingrate){/*{{{*/
    1468 
    1469         /* Check if ice in element */
    1470         if(!element->IsIceInElement()) return -1;
    1471 
    1472         /* Only update Constraints at the base of grounded ice*/
    1473         if(!(element->IsOnBase())) return -1;
    1474 
    1475         /*Intermediary*/
    1476         int state=-1;
    1477         IssmDouble      dt;
    1478 
    1479         /*Get parameters and inputs: */
    1480         element->FindParam(&dt,TimesteppingTimeStepEnum);
    1481 
    1482         if(enthalpy<PureIceEnthalpy(element,pressure)){
    1483                 if(watercolumn<=0.) state=0; // cold, dry base
    1484                 else state=1; // cold, wet base (refreezing)
    1485         }
    1486         else{
    1487                 if(enthalpyup<PureIceEnthalpy(element,pressureup)){
    1488                         if((dt==0.) && (meltingrate<0.)) state=2;       // refreezing temperate base (non-physical, only for steadystate solver)
    1489                         else    state=3; // temperate base, but no temperate layer
    1490                 }
    1491                 else state=4; // temperate layer with positive thickness
    1492         }
    1493 
    1494         _assert_(state>=0);
    1495         return state;
    1496 }/*}}}*/
    1497 IssmDouble EnthalpyAnalysis::GetWetIceConductivity(Element* element, IssmDouble enthalpy, IssmDouble pressure){/*{{{*/
    1498 
    1499         IssmDouble temperature, waterfraction;
    1500         IssmDouble kappa_w = 0.6; // thermal conductivity of water (in W/m/K)
    1501         IssmDouble kappa_i = element->GetMaterialParameter(MaterialsThermalconductivityEnum);
    1502         element->EnthalpyToThermal(&temperature, &waterfraction, enthalpy, pressure);
    1503 
    1504         return (1.-waterfraction)*kappa_i + waterfraction*kappa_w;
    1505 }/*}}}*/
    1506 
    1507 /*Intermediaries*/
    1508 IssmDouble EnthalpyAnalysis::EnthalpyDiffusionParameter(Element* element,IssmDouble enthalpy,IssmDouble pressure){/*{{{*/
     1031        /* Only drain waterfraction of ice column from element at base*/
     1032        if(!element->IsOnBase()) return; //FIXME: allow freeze on for floating elements
     1033
     1034        /* Intermediaries*/
     1035        int is, numvertices, numsegments;
     1036        int *pairindices   = NULL;
     1037
     1038        numvertices=element->GetNumberOfVertices();
     1039        element->VerticalSegmentIndices(&pairindices,&numsegments);
     1040
     1041        IssmDouble* watercolumn = xNew<IssmDouble>(numvertices);
     1042        IssmDouble* drainrate_column  = xNew<IssmDouble>(numsegments);
     1043        IssmDouble* drainrate_element = xNew<IssmDouble>(numsegments);
     1044
     1045        element->GetInputListOnVertices(watercolumn,WatercolumnEnum);
     1046
     1047        for(is=0;is<numsegments;is++)   drainrate_column[is]=0.;
     1048        Element* elementi = element;
     1049        for(;;){
     1050                for(is=0;is<numsegments;is++)   drainrate_element[is]=0.;
     1051                DrainWaterfraction(elementi,drainrate_element); // TODO: make sure every vertex is only drained once
     1052                for(is=0;is<numsegments;is++)   drainrate_column[is]+=drainrate_element[is];
     1053
     1054                if(elementi->IsOnSurface()) break;
     1055                elementi=elementi->GetUpperElement();                   
     1056        }
     1057        /* add drained water to water column*/
     1058        for(is=0;is<numsegments;is++) watercolumn[is]+=drainrate_column[is];
     1059        /* Feed updated water column back into model */
     1060        element->AddInput(WatercolumnEnum,watercolumn,P1Enum);
     1061
     1062        xDelete<int>(pairindices);
     1063        xDelete<IssmDouble>(drainrate_column);
     1064        xDelete<IssmDouble>(drainrate_element);
     1065        xDelete<IssmDouble>(watercolumn);
     1066}/*}}}*/
     1067IssmDouble     EnthalpyAnalysis::EnthalpyDiffusionParameter(Element* element,IssmDouble enthalpy,IssmDouble pressure){/*{{{*/
    15091068
    15101069        IssmDouble heatcapacity             = element->GetMaterialParameter(MaterialsHeatcapacityEnum);
     
    15191078        }
    15201079}/*}}}*/
    1521 IssmDouble EnthalpyAnalysis::EnthalpyDiffusionParameterVolume(Element* element,int enthalpy_enum){/*{{{*/
     1080IssmDouble     EnthalpyAnalysis::EnthalpyDiffusionParameterVolume(Element* element,int enthalpy_enum){/*{{{*/
    15221081
    15231082        int         iv;
     
    15741133        return kappa;
    15751134}/*}}}*/
    1576 IssmDouble EnthalpyAnalysis::PureIceEnthalpy(Element* element,IssmDouble pressure){/*{{{*/
     1135void           EnthalpyAnalysis::GetBAdvec(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
     1136        /*Compute B  matrix. B=[B1 B2 B3 B4 B5 B6] where Bi is of size 5*NDOF1.
     1137         * For node i, Bi' can be expressed in the actual coordinate system
     1138         * by:
     1139         *       Bi_advec =[ h ]
     1140         *                 [ h ]
     1141         *                 [ h ]
     1142         * where h is the interpolation function for node i.
     1143         *
     1144         * We assume B has been allocated already, of size: 3x(NDOF1*NUMNODESP1)
     1145         */
     1146
     1147        /*Fetch number of nodes for this finite element*/
     1148        int numnodes = element->GetNumberOfNodes();
     1149
     1150        /*Get nodal functions*/
     1151        IssmDouble* basis=xNew<IssmDouble>(numnodes);
     1152        element->NodalFunctions(basis,gauss);
     1153
     1154        /*Build B: */
     1155        for(int i=0;i<numnodes;i++){
     1156                B[numnodes*0+i] = basis[i];
     1157                B[numnodes*1+i] = basis[i];
     1158                B[numnodes*2+i] = basis[i];
     1159        }
     1160
     1161        /*Clean-up*/
     1162        xDelete<IssmDouble>(basis);
     1163}/*}}}*/
     1164void           EnthalpyAnalysis::GetBAdvecprime(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
     1165        /*Compute B  matrix. B=[B1 B2 B3 B4 B5 B6] where Bi is of size 5*NDOF1.
     1166         * For node i, Bi' can be expressed in the actual coordinate system
     1167         * by:
     1168         *       Biprime_advec=[ dh/dx ]
     1169         *                     [ dh/dy ]
     1170         *                     [ dh/dz ]
     1171         * where h is the interpolation function for node i.
     1172         *
     1173         * We assume B has been allocated already, of size: 3x(NDOF1*numnodes)
     1174         */
     1175
     1176        /*Fetch number of nodes for this finite element*/
     1177        int numnodes = element->GetNumberOfNodes();
     1178
     1179        /*Get nodal functions derivatives*/
     1180        IssmDouble* dbasis=xNew<IssmDouble>(3*numnodes);
     1181        element->NodalFunctionsDerivatives(dbasis,xyz_list,gauss);
     1182
     1183        /*Build B: */
     1184        for(int i=0;i<numnodes;i++){
     1185                B[numnodes*0+i] = dbasis[0*numnodes+i];
     1186                B[numnodes*1+i] = dbasis[1*numnodes+i];
     1187                B[numnodes*2+i] = dbasis[2*numnodes+i];
     1188        }
     1189
     1190        /*Clean-up*/
     1191        xDelete<IssmDouble>(dbasis);
     1192}/*}}}*/
     1193void           EnthalpyAnalysis::GetBasalConstraints(Vector<IssmDouble>* vec_spc,Element* element){/*{{{*/
     1194
     1195        /* Check if ice in element */
     1196        if(!element->IsIceInElement()) return;
     1197
     1198        /* Only update Constraints at the base of grounded ice*/
     1199        if(!(element->IsOnBase()) || element->IsFloating()) return;
     1200
     1201        /*Intermediary*/
     1202        bool        isdynamicbasalspc;
     1203        IssmDouble      dt;
     1204
     1205        /*Check wether dynamic basal boundary conditions are activated */
     1206        element->FindParam(&isdynamicbasalspc,ThermalIsdynamicbasalspcEnum);
     1207        if(!isdynamicbasalspc) return;
     1208
     1209        element->FindParam(&dt,TimesteppingTimeStepEnum);
     1210        if(dt==0.){
     1211                GetBasalConstraintsSteadystate(vec_spc,element);
     1212        }
     1213        else{
     1214                GetBasalConstraintsTransient(vec_spc,element);
     1215        }
     1216}/*}}}*/
     1217void           EnthalpyAnalysis::GetBasalConstraintsSteadystate(Vector<IssmDouble>* vec_spc,Element* element){/*{{{*/
     1218
     1219        /* Check if ice in element */
     1220        if(!element->IsIceInElement()) return;
     1221
     1222        /* Only update Constraints at the base of grounded ice*/
     1223        if(!(element->IsOnBase()) || element->IsFloating()) return;
     1224
     1225        /*Intermediary*/
     1226        int         numindices, numindicesup, state;
     1227        int        *indices = NULL, *indicesup = NULL;
     1228        IssmDouble      enthalpy, enthalpyup, pressure, pressureup, watercolumn, meltingrate;
     1229
     1230        /*Get parameters and inputs: */
     1231        Input* enthalpy_input            = element->GetInput(EnthalpyPicardEnum);                                        _assert_(enthalpy_input);
     1232        Input* pressure_input            = element->GetInput(PressureEnum);                                                      _assert_(pressure_input);
     1233        Input* watercolumn_input         = element->GetInput(WatercolumnEnum);                                                   _assert_(watercolumn_input);
     1234        Input* meltingrate_input         = element->GetInput(BasalforcingsGroundediceMeltingRateEnum);                                                   _assert_(meltingrate_input);
     1235
     1236        /*Fetch indices of basal & surface nodes for this finite element*/
     1237        Penta *penta =  (Penta *) element; // TODO: add Basal-/SurfaceNodeIndices to element.h, and change this to Element*
     1238        penta->BasalNodeIndices(&numindices,&indices,element->GetElementType());
     1239        penta->SurfaceNodeIndices(&numindicesup,&indicesup,element->GetElementType());  _assert_(numindices==numindicesup);
     1240
     1241        GaussPenta* gauss=new GaussPenta();
     1242        GaussPenta* gaussup=new GaussPenta();
     1243        for(int i=0;i<numindices;i++){
     1244                gauss->GaussNode(element->GetElementType(),indices[i]);
     1245                gaussup->GaussNode(element->GetElementType(),indicesup[i]);
     1246
     1247                enthalpy_input->GetInputValue(&enthalpy,gauss);
     1248                enthalpy_input->GetInputValue(&enthalpyup,gaussup);
     1249                pressure_input->GetInputValue(&pressure,gauss);
     1250                pressure_input->GetInputValue(&pressureup,gaussup);
     1251                watercolumn_input->GetInputValue(&watercolumn,gauss);
     1252                meltingrate_input->GetInputValue(&meltingrate,gauss);
     1253
     1254                state=GetThermalBasalCondition(element, enthalpy, enthalpyup, pressure, pressureup, watercolumn, meltingrate);
     1255                switch (state) {
     1256                        case 0:
     1257                                // cold, dry base: apply basal surface forcing
     1258                                vec_spc->SetValue(element->nodes[i]->Sid(),0.,INS_VAL);
     1259                                break;
     1260                        case 1:
     1261                                // cold, wet base: keep at pressure melting point
     1262                                vec_spc->SetValue(element->nodes[i]->Sid(),1.,INS_VAL);
     1263                                break;
     1264                        case 2:
     1265                                // temperate, thin refreezing base: release spc
     1266                                vec_spc->SetValue(element->nodes[i]->Sid(),0.,INS_VAL);
     1267                                break;
     1268                        case 3:
     1269                                // temperate, thin melting base: set spc
     1270                                vec_spc->SetValue(element->nodes[i]->Sid(),1.,INS_VAL);
     1271                                break;
     1272                        case 4:
     1273                                // temperate, thick melting base: s
     1274                                vec_spc->SetValue(element->nodes[i]->Sid(),1.,INS_VAL);
     1275                                break;
     1276                        default:
     1277                                _printf0_("     unknown thermal basal state found!");
     1278                }
     1279        }
     1280
     1281        /*Free ressources:*/
     1282        xDelete<int>(indices);
     1283        xDelete<int>(indicesup);
     1284        delete gauss;
     1285        delete gaussup;
     1286}/*}}}*/
     1287void           EnthalpyAnalysis::GetBasalConstraintsTransient(Vector<IssmDouble>* vec_spc,Element* element){/*{{{*/
     1288
     1289        /* Check if ice in element */
     1290        if(!element->IsIceInElement()) return;
     1291
     1292        /* Only update Constraints at the base of grounded ice*/
     1293        if(!(element->IsOnBase()) || element->IsFloating()) return;
     1294
     1295        /*Intermediary*/
     1296        int         numindices, numindicesup, state;
     1297        int        *indices = NULL, *indicesup = NULL;
     1298        IssmDouble      enthalpy, enthalpyup, pressure, pressureup, watercolumn, meltingrate;
     1299
     1300        /*Get parameters and inputs: */
     1301        Input* enthalpy_input       = element->GetInput(EnthalpyEnum);                    _assert_(enthalpy_input); //TODO: check EnthalpyPicard?
     1302        Input* pressure_input            = element->GetInput(PressureEnum);                                                      _assert_(pressure_input);
     1303        Input* watercolumn_input         = element->GetInput(WatercolumnEnum);                                                   _assert_(watercolumn_input);
     1304        Input* meltingrate_input         = element->GetInput(BasalforcingsGroundediceMeltingRateEnum);                                                   _assert_(meltingrate_input);
     1305
     1306        /*Fetch indices of basal & surface nodes for this finite element*/
     1307        Penta *penta =  (Penta *) element; // TODO: add Basal-/SurfaceNodeIndices to element.h, and change this to Element*
     1308        penta->BasalNodeIndices(&numindices,&indices,element->GetElementType());
     1309        penta->SurfaceNodeIndices(&numindicesup,&indicesup,element->GetElementType());  _assert_(numindices==numindicesup);
     1310
     1311        GaussPenta* gauss=new GaussPenta();
     1312        GaussPenta* gaussup=new GaussPenta();
     1313
     1314        for(int i=0;i<numindices;i++){
     1315                gauss->GaussNode(element->GetElementType(),indices[i]);
     1316                gaussup->GaussNode(element->GetElementType(),indicesup[i]);
     1317               
     1318                enthalpy_input->GetInputValue(&enthalpy,gauss);
     1319                enthalpy_input->GetInputValue(&enthalpyup,gaussup);
     1320                pressure_input->GetInputValue(&pressure,gauss);
     1321                pressure_input->GetInputValue(&pressureup,gaussup);
     1322                watercolumn_input->GetInputValue(&watercolumn,gauss);
     1323                meltingrate_input->GetInputValue(&meltingrate,gauss);
     1324
     1325                state=GetThermalBasalCondition(element, enthalpy, enthalpyup, pressure, pressureup, watercolumn, meltingrate);
     1326
     1327                switch (state) {
     1328                        case 0:
     1329                                // cold, dry base: apply basal surface forcing
     1330                                vec_spc->SetValue(element->nodes[i]->Sid(),0.,INS_VAL);
     1331                                break;
     1332                        case 1:
     1333                                // cold, wet base: keep at pressure melting point
     1334                                vec_spc->SetValue(element->nodes[i]->Sid(),1.,INS_VAL);
     1335                                break;
     1336                        case 2:
     1337                                // temperate, thin refreezing base: release spc
     1338                                vec_spc->SetValue(element->nodes[i]->Sid(),0.,INS_VAL);
     1339                                break;
     1340                        case 3:
     1341                                // temperate, thin melting base: set spc
     1342                                vec_spc->SetValue(element->nodes[i]->Sid(),1.,INS_VAL);
     1343                                break;
     1344                        case 4:
     1345                                // temperate, thick melting base: set grad H*n=0
     1346                                vec_spc->SetValue(element->nodes[i]->Sid(),0.,INS_VAL);
     1347                                break;
     1348                        default:
     1349                                _printf0_("     unknown thermal basal state found!");
     1350                }
     1351
     1352        }
     1353
     1354        /*Free ressources:*/
     1355        xDelete<int>(indices);
     1356        xDelete<int>(indicesup);
     1357        delete gauss;
     1358        delete gaussup;
     1359}/*}}}*/
     1360void           EnthalpyAnalysis::GetBConduct(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
     1361        /*Compute B  matrix. B=[B1 B2 B3 B4 B5 B6] where Bi is of size 5*NDOF1.
     1362         * For node i, Bi' can be expressed in the actual coordinate system
     1363         * by:
     1364         *       Bi_conduct=[ dh/dx ]
     1365         *                  [ dh/dy ]
     1366         *                  [ dh/dz ]
     1367         * where h is the interpolation function for node i.
     1368         *
     1369         * We assume B has been allocated already, of size: 3x(NDOF1*numnodes)
     1370         */
     1371
     1372        /*Fetch number of nodes for this finite element*/
     1373        int numnodes = element->GetNumberOfNodes();
     1374
     1375        /*Get nodal functions derivatives*/
     1376        IssmDouble* dbasis=xNew<IssmDouble>(3*numnodes);
     1377        element->NodalFunctionsDerivatives(dbasis,xyz_list,gauss);
     1378
     1379        /*Build B: */
     1380        for(int i=0;i<numnodes;i++){
     1381                B[numnodes*0+i] = dbasis[0*numnodes+i];
     1382                B[numnodes*1+i] = dbasis[1*numnodes+i];
     1383                B[numnodes*2+i] = dbasis[2*numnodes+i];
     1384        }
     1385
     1386        /*Clean-up*/
     1387        xDelete<IssmDouble>(dbasis);
     1388}/*}}}*/
     1389void           EnthalpyAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
     1390        element->GetSolutionFromInputsOneDof(solution,EnthalpyEnum);
     1391}/*}}}*/
     1392int            EnthalpyAnalysis::GetThermalBasalCondition(Element* element, IssmDouble enthalpy, IssmDouble enthalpyup, IssmDouble pressure, IssmDouble pressureup, IssmDouble watercolumn, IssmDouble meltingrate){/*{{{*/
     1393
     1394        /* Check if ice in element */
     1395        if(!element->IsIceInElement()) return -1;
     1396
     1397        /* Only update Constraints at the base of grounded ice*/
     1398        if(!(element->IsOnBase())) return -1;
     1399
     1400        /*Intermediary*/
     1401        int state=-1;
     1402        IssmDouble      dt;
     1403
     1404        /*Get parameters and inputs: */
     1405        element->FindParam(&dt,TimesteppingTimeStepEnum);
     1406
     1407        if(enthalpy<PureIceEnthalpy(element,pressure)){
     1408                if(watercolumn<=0.) state=0; // cold, dry base
     1409                else state=1; // cold, wet base (refreezing)
     1410        }
     1411        else{
     1412                if(enthalpyup<PureIceEnthalpy(element,pressureup)){
     1413                        if((dt==0.) && (meltingrate<0.)) state=2;       // refreezing temperate base (non-physical, only for steadystate solver)
     1414                        else    state=3; // temperate base, but no temperate layer
     1415                }
     1416                else state=4; // temperate layer with positive thickness
     1417        }
     1418
     1419        _assert_(state>=0);
     1420        return state;
     1421}/*}}}*/
     1422IssmDouble     EnthalpyAnalysis::GetWetIceConductivity(Element* element, IssmDouble enthalpy, IssmDouble pressure){/*{{{*/
     1423
     1424        IssmDouble temperature, waterfraction;
     1425        IssmDouble kappa_w = 0.6; // thermal conductivity of water (in W/m/K)
     1426        IssmDouble kappa_i = element->GetMaterialParameter(MaterialsThermalconductivityEnum);
     1427        element->EnthalpyToThermal(&temperature, &waterfraction, enthalpy, pressure);
     1428
     1429        return (1.-waterfraction)*kappa_i + waterfraction*kappa_w;
     1430}/*}}}*/
     1431void           EnthalpyAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
     1432        _error_("Not implemented yet");
     1433}/*}}}*/
     1434void           EnthalpyAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
     1435
     1436        bool        converged;
     1437        int         i,rheology_law;
     1438        IssmDouble  B_average,s_average,T_average=0.,P_average=0.;
     1439        int        *doflist   = NULL;
     1440        IssmDouble *xyz_list  = NULL;
     1441
     1442        /*Fetch number of nodes and dof for this finite element*/
     1443        int numnodes    = element->GetNumberOfNodes();
     1444
     1445        /*Fetch dof list and allocate solution vector*/
     1446        element->GetDofList(&doflist,NoneApproximationEnum,GsetEnum);
     1447        IssmDouble* values        = xNew<IssmDouble>(numnodes);
     1448        IssmDouble* pressure      = xNew<IssmDouble>(numnodes);
     1449        IssmDouble* surface       = xNew<IssmDouble>(numnodes);
     1450        IssmDouble* B             = xNew<IssmDouble>(numnodes);
     1451        IssmDouble* temperature   = xNew<IssmDouble>(numnodes);
     1452        IssmDouble* waterfraction = xNew<IssmDouble>(numnodes);
     1453
     1454        /*Use the dof list to index into the solution vector: */
     1455        for(i=0;i<numnodes;i++){
     1456                values[i]=solution[doflist[i]];
     1457
     1458                /*Check solution*/
     1459                if(xIsNan<IssmDouble>(values[i])) _error_("NaN found in solution vector");
     1460        }
     1461
     1462        /*Get all inputs and parameters*/
     1463        element->GetInputValue(&converged,ConvergedEnum);
     1464        element->GetInputListOnNodes(&pressure[0],PressureEnum);
     1465        if(converged){
     1466                for(i=0;i<numnodes;i++){
     1467                        element->EnthalpyToThermal(&temperature[i],&waterfraction[i],values[i],pressure[i]);
     1468                        if(waterfraction[i]<0.) _error_("Negative water fraction found in solution vector");
     1469                        //if(waterfraction[i]>1.) _error_("Water fraction >1 found in solution vector");
     1470                }
     1471                element->AddInput(EnthalpyEnum,values,element->GetElementType());
     1472                element->AddInput(WaterfractionEnum,waterfraction,element->GetElementType());
     1473                element->AddInput(TemperatureEnum,temperature,element->GetElementType());
     1474
     1475                /*Update Rheology only if converged (we must make sure that the temperature is below melting point
     1476                 * otherwise the rheology could be negative*/
     1477                element->FindParam(&rheology_law,MaterialsRheologyLawEnum);
     1478                element->GetInputListOnNodes(&surface[0],SurfaceEnum);
     1479                switch(rheology_law){
     1480                        case NoneEnum:
     1481                                /*Do nothing: B is not temperature dependent*/
     1482                                break;
     1483                        case CuffeyEnum:
     1484                                for(i=0;i<numnodes;i++) B[i]=Cuffey(temperature[i]);
     1485                                element->AddInput(MaterialsRheologyBEnum,&B[0],element->GetElementType());
     1486                                break;
     1487                        case PatersonEnum:
     1488                                for(i=0;i<numnodes;i++) B[i]=Paterson(temperature[i]);
     1489                                element->AddInput(MaterialsRheologyBEnum,&B[0],element->GetElementType());
     1490                                break;
     1491                        case ArrheniusEnum:
     1492                                element->GetVerticesCoordinates(&xyz_list);
     1493                                for(i=0;i<numnodes;i++) B[i]=Arrhenius(temperature[i],surface[i]-xyz_list[i*3+2],element->GetMaterialParameter(MaterialsRheologyNEnum));
     1494                                element->AddInput(MaterialsRheologyBEnum,&B[0],element->GetElementType());
     1495                                break;
     1496                        case LliboutryDuvalEnum:
     1497                                for(i=0;i<numnodes;i++) B[i]=LliboutryDuval(values[i],pressure[i],element->GetMaterialParameter(MaterialsRheologyNEnum),element->GetMaterialParameter(MaterialsBetaEnum),element->GetMaterialParameter(ConstantsReferencetemperatureEnum),element->GetMaterialParameter(MaterialsHeatcapacityEnum),element->GetMaterialParameter(MaterialsLatentheatEnum));
     1498                                element->AddInput(MaterialsRheologyBEnum,&B[0],element->GetElementType());
     1499                                break;
     1500                        default: _error_("Rheology law " << EnumToStringx(rheology_law) << " not supported yet");
     1501                }
     1502        }
     1503        else{
     1504                element->AddInput(EnthalpyPicardEnum,values,element->GetElementType());
     1505        }
     1506
     1507        /*Free ressources:*/
     1508        xDelete<IssmDouble>(values);
     1509        xDelete<IssmDouble>(pressure);
     1510        xDelete<IssmDouble>(surface);
     1511        xDelete<IssmDouble>(B);
     1512        xDelete<IssmDouble>(temperature);
     1513        xDelete<IssmDouble>(waterfraction);
     1514        xDelete<IssmDouble>(xyz_list);
     1515        xDelete<int>(doflist);
     1516}/*}}}*/
     1517void           EnthalpyAnalysis::PostProcessing(FemModel* femmodel){/*{{{*/
     1518
     1519        /*Intermediaries*/
     1520        bool computebasalmeltingrates=true;
     1521        bool drainicecolumn=true;
     1522        bool isdynamicbasalspc;
     1523        IssmDouble dt;
     1524
     1525        femmodel->parameters->FindParam(&isdynamicbasalspc,ThermalIsdynamicbasalspcEnum);
     1526        femmodel->parameters->FindParam(&dt,TimesteppingTimeStepEnum);
     1527
     1528        //TODO: use dt to decide what to do
     1529        if(drainicecolumn)      DrainWaterfraction(femmodel);
     1530        if(computebasalmeltingrates)    ComputeBasalMeltingrate(femmodel);
     1531        if(isdynamicbasalspc)   UpdateBasalConstraints(femmodel);
     1532
     1533}/*}}}*/
     1534IssmDouble     EnthalpyAnalysis::PureIceEnthalpy(Element* element,IssmDouble pressure){/*{{{*/
    15771535
    15781536        IssmDouble heatcapacity         = element->GetMaterialParameter(MaterialsHeatcapacityEnum);
     
    15811539        return heatcapacity*(TMeltingPoint(element,pressure)-referencetemperature);
    15821540}/*}}}*/
    1583 IssmDouble EnthalpyAnalysis::TMeltingPoint(Element* element,IssmDouble pressure){/*{{{*/
     1541IssmDouble     EnthalpyAnalysis::TMeltingPoint(Element* element,IssmDouble pressure){/*{{{*/
    15841542
    15851543        IssmDouble meltingpoint = element->GetMaterialParameter(MaterialsMeltingpointEnum);
     
    15881546        return meltingpoint-beta*pressure;
    15891547}/*}}}*/
     1548void           EnthalpyAnalysis::UpdateBasalConstraints(FemModel* femmodel){/*{{{*/
     1549
     1550        /*Update basal dirichlet BCs for enthalpy: */
     1551        Vector<IssmDouble>* spc           = NULL;
     1552        IssmDouble*         serial_spc    = NULL;
     1553
     1554        spc=new Vector<IssmDouble>(femmodel->nodes->NumberOfNodes(EnthalpyAnalysisEnum));
     1555        /*First create a vector to figure out what elements should be constrained*/
     1556        for(int i=0;i<femmodel->elements->Size();i++){
     1557                Element* element=xDynamicCast<Element*>(femmodel->elements->GetObjectByOffset(i));
     1558                GetBasalConstraints(spc,element);
     1559        }
     1560
     1561        /*Assemble and serialize*/
     1562        spc->Assemble();
     1563        serial_spc=spc->ToMPISerial();
     1564        delete spc;
     1565
     1566        /*Then update basal constraints nodes accordingly*/
     1567        for(int i=0;i<femmodel->elements->Size();i++){
     1568                Element* element=xDynamicCast<Element*>(femmodel->elements->GetObjectByOffset(i));
     1569                ApplyBasalConstraints(serial_spc,element);
     1570        }
     1571
     1572        femmodel->UpdateConstraintsx();
     1573
     1574        /*Delete*/
     1575        xDelete<IssmDouble>(serial_spc);
     1576}/*}}}*/
     1577void           EnthalpyAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
     1578
     1579        bool islevelset;
     1580        femmodel->parameters->FindParam(&islevelset,TransientIslevelsetEnum);
     1581        if(islevelset){
     1582                SetActiveNodesLSMx(femmodel);
     1583        }
     1584        return;
     1585}/*}}}*/
  • issm/trunk-jpl/src/c/analyses/EnthalpyAnalysis.h

    r18659 r18930  
    1414        public:
    1515                /*Model processing*/
    16                 int  DofsPerNode(int** doflist,int domaintype,int approximation);
    17                 void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);
    18                 void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);
    19                 void CreateNodes(Nodes* nodes,IoModel* iomodel);
    2016                void CreateConstraints(Constraints* constraints,IoModel* iomodel);
    2117                void CreateLoads(Loads* loads, IoModel* iomodel);
     18                void CreateNodes(Nodes* nodes,IoModel* iomodel);
     19                int  DofsPerNode(int** doflist,int domaintype,int approximation);
     20                void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);
     21                void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);
    2222
    2323                /*Finite element Analysis*/
    24                 void           Core(FemModel* femmodel);
    25                 ElementVector* CreateDVector(Element* element);
    26                 ElementMatrix* CreateJacobianMatrix(Element* element);
    27                 ElementMatrix* CreateKMatrix(Element* element);
    28                 ElementMatrix* CreateKMatrixVolume(Element* element);
    29                 ElementMatrix* CreateKMatrixShelf(Element* element);
    30                 ElementVector* CreatePVector(Element* element);
    31                 ElementVector* CreatePVectorVolume(Element* element);
    32                 ElementVector* CreatePVectorSheet(Element* element);
    33                 ElementVector* CreatePVectorShelf(Element* element);
    34                 void GetBConduct(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss);
    35                 void GetBAdvec(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss);
    36                 void GetBAdvecprime(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss);
    37                 void GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);
    38                 void GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);
    39                 void InputUpdateFromSolution(IssmDouble* solution,Element* element);
    40                 void UpdateConstraints(FemModel* femmodel);
    41 
    42                 /*Modules*/
    43                 static void PostProcessing(FemModel* femmodel);
    44                 static void ComputeBasalMeltingrate(FemModel* femmodel);
    45                 static void ComputeBasalMeltingrate(Element* element);
    46                 static void DrainWaterfraction(FemModel* femmodel);
    47                 static void DrainWaterfractionIcecolumn(Element* element);
    48                 static void DrainWaterfraction(Element* element, IssmDouble* pdrainrate_element);
    49                 static void UpdateBasalConstraints(FemModel* femmodel);
    50                 static void ApplyBasalConstraints(IssmDouble* serial_spc,Element* element);
    51                 static void GetBasalConstraints(Vector<IssmDouble>* vec_spc,Element* element);
    52                 static void GetBasalConstraintsTransient(Vector<IssmDouble>* vec_spc,Element* element);
    53                 static void GetBasalConstraintsSteadystate(Vector<IssmDouble>* vec_spc,Element* element);
    54                 static int GetThermalBasalCondition(Element* element, IssmDouble enthalpy, IssmDouble enthalpy_up, IssmDouble pressure, IssmDouble pressure_up, IssmDouble watercolumn, IssmDouble meltingrate);
    55                 static IssmDouble GetWetIceConductivity(Element* element, IssmDouble enthalpy, IssmDouble pressure);
    56 
    57 
    58                 /*Intermediaries*/
     24                static void       ApplyBasalConstraints(IssmDouble* serial_spc,Element* element);
     25                static void       ComputeBasalMeltingrate(FemModel* femmodel);
     26                static void       ComputeBasalMeltingrate(Element* element);
     27                void              Core(FemModel* femmodel);
     28                ElementVector*    CreateDVector(Element* element);
     29                ElementMatrix*    CreateJacobianMatrix(Element* element);
     30                ElementMatrix*    CreateKMatrix(Element* element);
     31                ElementMatrix*    CreateKMatrixVolume(Element* element);
     32                ElementMatrix*    CreateKMatrixShelf(Element* element);
     33                ElementVector*    CreatePVector(Element* element);
     34                ElementVector*    CreatePVectorVolume(Element* element);
     35                ElementVector*    CreatePVectorSheet(Element* element);
     36                ElementVector*    CreatePVectorShelf(Element* element);
     37                static void       DrainWaterfraction(FemModel* femmodel);
     38                static void       DrainWaterfraction(Element* element, IssmDouble* pdrainrate_element);
     39                static void       DrainWaterfractionIcecolumn(Element* element);
    5940                static IssmDouble EnthalpyDiffusionParameter(Element* element,IssmDouble enthalpy,IssmDouble pressure);
    6041                static IssmDouble EnthalpyDiffusionParameterVolume(Element* element,int enthalpy_enum);
     42                void              GetBAdvec(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss);
     43                void              GetBAdvecprime(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss);
     44                static void       GetBasalConstraints(Vector<IssmDouble>* vec_spc,Element* element);
     45                static void       GetBasalConstraintsSteadystate(Vector<IssmDouble>* vec_spc,Element* element);
     46                static void       GetBasalConstraintsTransient(Vector<IssmDouble>* vec_spc,Element* element);
     47                void              GetBConduct(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss);
     48                void              GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);
     49                static int        GetThermalBasalCondition(Element* element, IssmDouble enthalpy, IssmDouble enthalpy_up, IssmDouble pressure, IssmDouble pressure_up, IssmDouble watercolumn, IssmDouble meltingrate);
     50                static IssmDouble GetWetIceConductivity(Element* element, IssmDouble enthalpy, IssmDouble pressure);
     51                void              GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);
     52                void              InputUpdateFromSolution(IssmDouble* solution,Element* element);
     53                static void       PostProcessing(FemModel* femmodel);
    6154                static IssmDouble PureIceEnthalpy(Element* element,IssmDouble pressure);
    6255                static IssmDouble TMeltingPoint(Element* element,IssmDouble pressure);
     56                static void       UpdateBasalConstraints(FemModel* femmodel);
     57                void              UpdateConstraints(FemModel* femmodel);
    6358};
    6459#endif
  • issm/trunk-jpl/src/c/analyses/HydrologyShreveAnalysis.cpp

    r18068 r18930  
    66
    77/*Model processing*/
     8void HydrologyShreveAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
     9
     10        /*retrieve some parameters: */
     11        int          hydrology_model;
     12        iomodel->Constant(&hydrology_model,HydrologyModelEnum);
     13
     14        if(hydrology_model!=HydrologyshreveEnum) return;
     15
     16        IoModelToConstraintsx(constraints,iomodel,HydrologyshreveSpcwatercolumnEnum,HydrologyShreveAnalysisEnum,P1Enum);
     17
     18}/*}}}*/
     19void HydrologyShreveAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
     20        /*No loads*/
     21}/*}}}*/
     22void HydrologyShreveAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
     23
     24        /*Fetch parameters: */
     25        int  hydrology_model;
     26        iomodel->Constant(&hydrology_model,HydrologyModelEnum);
     27
     28        /*Now, do we really want Shreve?*/
     29        if(hydrology_model!=HydrologyshreveEnum) return;
     30
     31        if(iomodel->domaintype==Domain3DEnum) iomodel->FetchData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum);
     32        ::CreateNodes(nodes,iomodel,HydrologyShreveAnalysisEnum,P1Enum);
     33        iomodel->DeleteData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum);
     34}/*}}}*/
    835int  HydrologyShreveAnalysis::DofsPerNode(int** doflist,int domaintype,int approximation){/*{{{*/
    936        return 1;
    10 }/*}}}*/
    11 void HydrologyShreveAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
    12 
    13         /*retrieve some parameters: */
    14         int  hydrology_model;
    15         iomodel->Constant(&hydrology_model,HydrologyModelEnum);
    16 
    17         /*Now, do we really want Shreve?*/
    18         if(hydrology_model!=HydrologyshreveEnum) return;
    19 
    20         parameters->AddObject(new IntParam(HydrologyModelEnum,hydrology_model));
    21         parameters->AddObject(iomodel->CopyConstantObject(HydrologyshreveStabilizationEnum));
    22 
    2337}/*}}}*/
    2438void HydrologyShreveAnalysis::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/
     
    5569        elements->InputDuplicate(WatercolumnEnum,WaterColumnOldEnum);
    5670}/*}}}*/
    57 void HydrologyShreveAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
    58 
    59         /*Fetch parameters: */
     71void HydrologyShreveAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
     72
     73        /*retrieve some parameters: */
    6074        int  hydrology_model;
    6175        iomodel->Constant(&hydrology_model,HydrologyModelEnum);
     
    6478        if(hydrology_model!=HydrologyshreveEnum) return;
    6579
    66         if(iomodel->domaintype==Domain3DEnum) iomodel->FetchData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum);
    67         ::CreateNodes(nodes,iomodel,HydrologyShreveAnalysisEnum,P1Enum);
    68         iomodel->DeleteData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum);
    69 }/*}}}*/
    70 void HydrologyShreveAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
    71 
    72         /*retrieve some parameters: */
    73         int          hydrology_model;
    74         iomodel->Constant(&hydrology_model,HydrologyModelEnum);
    75 
    76         if(hydrology_model!=HydrologyshreveEnum) return;
    77 
    78         IoModelToConstraintsx(constraints,iomodel,HydrologyshreveSpcwatercolumnEnum,HydrologyShreveAnalysisEnum,P1Enum);
    79 
    80 }/*}}}*/
    81 void HydrologyShreveAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
    82         /*No loads*/
     80        parameters->AddObject(new IntParam(HydrologyModelEnum,hydrology_model));
     81        parameters->AddObject(iomodel->CopyConstantObject(HydrologyshreveStabilizationEnum));
     82
    8383}/*}}}*/
    8484
     
    9090        /*Default, return NULL*/
    9191        return NULL;
     92}/*}}}*/
     93void           HydrologyShreveAnalysis::CreateHydrologyWaterVelocityInput(Element* element){/*{{{*/
     94
     95        /*Intermediaries*/
     96        IssmDouble dsdx,dsdy,dbdx,dbdy,w;
     97
     98        /*Retrieve all inputs and parameters*/
     99        IssmDouble  rho_ice   = element->GetMaterialParameter(MaterialsRhoIceEnum);
     100        IssmDouble  rho_water = element->GetMaterialParameter(MaterialsRhoSeawaterEnum);
     101        IssmDouble  g         = element->GetMaterialParameter(ConstantsGEnum);
     102        IssmDouble  mu_water  = element->GetMaterialParameter(MaterialsMuWaterEnum);
     103        Input* surfaceslopex_input = element->GetInput(SurfaceSlopeXEnum); _assert_(surfaceslopex_input);
     104        Input* surfaceslopey_input = element->GetInput(SurfaceSlopeYEnum); _assert_(surfaceslopey_input);
     105        Input* bedslopex_input     = element->GetInput(BedSlopeXEnum);     _assert_(bedslopex_input);
     106        Input* bedslopey_input     = element->GetInput(BedSlopeYEnum);     _assert_(bedslopey_input);
     107        Input* watercolumn_input   = element->GetInput(WatercolumnEnum);   _assert_(watercolumn_input);
     108
     109        /*Fetch number of vertices and allocate output*/
     110        int numvertices = element->GetNumberOfVertices();
     111        IssmDouble* vx  = xNew<IssmDouble>(numvertices);
     112        IssmDouble* vy  = xNew<IssmDouble>(numvertices);
     113
     114        Gauss* gauss=element->NewGauss();
     115        for(int iv=0;iv<numvertices;iv++){
     116                gauss->GaussVertex(iv);
     117                surfaceslopex_input->GetInputValue(&dsdx,gauss);
     118                surfaceslopey_input->GetInputValue(&dsdy,gauss);
     119                bedslopex_input->GetInputValue(&dbdx,gauss);
     120                bedslopey_input->GetInputValue(&dbdy,gauss);
     121                watercolumn_input->GetInputValue(&w,gauss);
     122
     123                /* Water velocity x and y components */
     124                vx[iv]= - w*w/(12 * mu_water)*(rho_ice*g*dsdx+(rho_water-rho_ice)*g*dbdx);
     125                vy[iv]= - w*w/(12 * mu_water)*(rho_ice*g*dsdy+(rho_water-rho_ice)*g*dbdy);
     126        }
     127
     128        /*clean-up*/
     129        delete gauss;
     130
     131        /*Add to inputs*/
     132        element->AddInput(HydrologyWaterVxEnum,vx,P1Enum);
     133        element->AddInput(HydrologyWaterVyEnum,vy,P1Enum);
     134        xDelete<IssmDouble>(vx);
     135        xDelete<IssmDouble>(vy);
    92136}/*}}}*/
    93137ElementMatrix* HydrologyShreveAnalysis::CreateJacobianMatrix(Element* element){/*{{{*/
     
    234278        return pe;
    235279}/*}}}*/
    236 void HydrologyShreveAnalysis::GetB(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
     280void           HydrologyShreveAnalysis::GetB(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
    237281        /*Compute B  matrix. B=[B1 B2 B3] where Bi is of size 3*NDOF2.
    238282         * For node i, Bi can be expressed in the actual coordinate system
     
    261305        xDelete<IssmDouble>(basis);
    262306}/*}}}*/
    263 void HydrologyShreveAnalysis::GetBprime(IssmDouble* Bprime,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
     307void           HydrologyShreveAnalysis::GetBprime(IssmDouble* Bprime,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
    264308        /*Compute B'  matrix. B'=[B1' B2' B3'] where Bi' is of size 3*NDOF2.
    265309         * For node i, Bi' can be expressed in the actual coordinate system
     
    289333
    290334}/*}}}*/
    291 void HydrologyShreveAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
     335void           HydrologyShreveAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
    292336        element->GetSolutionFromInputsOneDof(solution,WatercolumnEnum);
    293337}/*}}}*/
    294 void HydrologyShreveAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
     338void           HydrologyShreveAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
    295339        _error_("Not implemented yet");
    296340}/*}}}*/
    297 void HydrologyShreveAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
     341void           HydrologyShreveAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
    298342
    299343        /*Intermediary*/
     
    321365        xDelete<int>(doflist);
    322366}/*}}}*/
    323 void HydrologyShreveAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
     367void           HydrologyShreveAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
    324368        /*Default, do nothing*/
    325369        return;
    326370}/*}}}*/
    327 
    328 /*Intermediaries*/
    329 void HydrologyShreveAnalysis::CreateHydrologyWaterVelocityInput(Element* element){/*{{{*/
    330 
    331         /*Intermediaries*/
    332         IssmDouble dsdx,dsdy,dbdx,dbdy,w;
    333 
    334         /*Retrieve all inputs and parameters*/
    335         IssmDouble  rho_ice   = element->GetMaterialParameter(MaterialsRhoIceEnum);
    336         IssmDouble  rho_water = element->GetMaterialParameter(MaterialsRhoSeawaterEnum);
    337         IssmDouble  g         = element->GetMaterialParameter(ConstantsGEnum);
    338         IssmDouble  mu_water  = element->GetMaterialParameter(MaterialsMuWaterEnum);
    339         Input* surfaceslopex_input = element->GetInput(SurfaceSlopeXEnum); _assert_(surfaceslopex_input);
    340         Input* surfaceslopey_input = element->GetInput(SurfaceSlopeYEnum); _assert_(surfaceslopey_input);
    341         Input* bedslopex_input     = element->GetInput(BedSlopeXEnum);     _assert_(bedslopex_input);
    342         Input* bedslopey_input     = element->GetInput(BedSlopeYEnum);     _assert_(bedslopey_input);
    343         Input* watercolumn_input   = element->GetInput(WatercolumnEnum);   _assert_(watercolumn_input);
    344 
    345         /*Fetch number of vertices and allocate output*/
    346         int numvertices = element->GetNumberOfVertices();
    347         IssmDouble* vx  = xNew<IssmDouble>(numvertices);
    348         IssmDouble* vy  = xNew<IssmDouble>(numvertices);
    349 
    350         Gauss* gauss=element->NewGauss();
    351         for(int iv=0;iv<numvertices;iv++){
    352                 gauss->GaussVertex(iv);
    353                 surfaceslopex_input->GetInputValue(&dsdx,gauss);
    354                 surfaceslopey_input->GetInputValue(&dsdy,gauss);
    355                 bedslopex_input->GetInputValue(&dbdx,gauss);
    356                 bedslopey_input->GetInputValue(&dbdy,gauss);
    357                 watercolumn_input->GetInputValue(&w,gauss);
    358 
    359                 /* Water velocity x and y components */
    360                 vx[iv]= - w*w/(12 * mu_water)*(rho_ice*g*dsdx+(rho_water-rho_ice)*g*dbdx);
    361                 vy[iv]= - w*w/(12 * mu_water)*(rho_ice*g*dsdy+(rho_water-rho_ice)*g*dbdy);
    362         }
    363 
    364         /*clean-up*/
    365         delete gauss;
    366 
    367         /*Add to inputs*/
    368         element->AddInput(HydrologyWaterVxEnum,vx,P1Enum);
    369         element->AddInput(HydrologyWaterVyEnum,vy,P1Enum);
    370         xDelete<IssmDouble>(vx);
    371         xDelete<IssmDouble>(vy);
    372 }/*}}}*/
    373 
    374371
    375372
  • issm/trunk-jpl/src/c/analyses/HydrologyShreveAnalysis.h

    r18057 r18930  
    1313        public:
    1414                /*Model processing*/
    15                 int  DofsPerNode(int** doflist,int domaintype,int approximation);
    16                 void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);
    17                 void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);
    18                 void CreateNodes(Nodes* nodes,IoModel* iomodel);
    1915                void CreateConstraints(Constraints* constraints,IoModel* iomodel);
    2016                void CreateLoads(Loads* loads, IoModel* iomodel);
     17                void CreateNodes(Nodes* nodes,IoModel* iomodel);
     18                int  DofsPerNode(int** doflist,int domaintype,int approximation);
     19                void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);
     20                void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);
    2121
    2222                /*Finite element Analysis*/
    2323                void           Core(FemModel* femmodel);
    2424                ElementVector* CreateDVector(Element* element);
     25                void           CreateHydrologyWaterVelocityInput(Element* element);
    2526                ElementMatrix* CreateJacobianMatrix(Element* element);
    2627                ElementMatrix* CreateKMatrix(Element* element);
    2728                ElementVector* CreatePVector(Element* element);
    28                 void GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);
    29                 void GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);
    30                 void InputUpdateFromSolution(IssmDouble* solution,Element* element);
    31                 void UpdateConstraints(FemModel* femmodel);
    32 
    33                 /*Intermediaries*/
    34                 void GetB(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss);
    35                 void GetBprime(IssmDouble* Bprime,Element* element,IssmDouble* xyz_list,Gauss* gauss);
    36                 void CreateHydrologyWaterVelocityInput(Element* element);
     29                void           GetB(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss);
     30                void           GetBprime(IssmDouble* Bprime,Element* element,IssmDouble* xyz_list,Gauss* gauss);
     31                void           GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);
     32                void           GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);
     33                void           InputUpdateFromSolution(IssmDouble* solution,Element* element);
     34                void           UpdateConstraints(FemModel* femmodel);
    3735};
    3836#endif
  • issm/trunk-jpl/src/c/analyses/L2ProjectionBaseAnalysis.cpp

    r18593 r18930  
    66
    77/*Model processing*/
     8void L2ProjectionBaseAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
     9
     10        /*No constraints*/
     11}/*}}}*/
     12void L2ProjectionBaseAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
     13
     14        /*No loads*/
     15}/*}}}*/
     16void L2ProjectionBaseAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
     17
     18        if(iomodel->domaintype==Domain3DEnum){
     19                iomodel->FetchData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum);
     20        }
     21        else if(iomodel->domaintype==Domain2DverticalEnum){
     22                iomodel->FetchData(1,MeshVertexonbaseEnum);
     23        }
     24        ::CreateNodes(nodes,iomodel,L2ProjectionBaseAnalysisEnum,P1Enum);
     25        iomodel->DeleteData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum);
     26}/*}}}*/
    827int  L2ProjectionBaseAnalysis::DofsPerNode(int** doflist,int domaintype,int approximation){/*{{{*/
    928        return 1;
    10 }/*}}}*/
    11 void L2ProjectionBaseAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
    1229}/*}}}*/
    1330void L2ProjectionBaseAnalysis::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/
     
    3148        }
    3249}/*}}}*/
    33 void L2ProjectionBaseAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
    34 
    35         if(iomodel->domaintype==Domain3DEnum){
    36                 iomodel->FetchData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum);
    37         }
    38         else if(iomodel->domaintype==Domain2DverticalEnum){
    39                 iomodel->FetchData(1,MeshVertexonbaseEnum);
    40         }
    41         ::CreateNodes(nodes,iomodel,L2ProjectionBaseAnalysisEnum,P1Enum);
    42         iomodel->DeleteData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum);
    43 }/*}}}*/
    44 void L2ProjectionBaseAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
    45 
    46         /*No constraints*/
    47 }/*}}}*/
    48 void L2ProjectionBaseAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
    49 
    50         /*No loads*/
     50void L2ProjectionBaseAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
    5151}/*}}}*/
    5252
     
    196196        return pe;
    197197}/*}}}*/
    198 void L2ProjectionBaseAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
     198void           L2ProjectionBaseAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
    199199           _error_("not implemented yet");
    200200}/*}}}*/
    201 void L2ProjectionBaseAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
     201void           L2ProjectionBaseAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
    202202        _error_("Not implemented yet");
    203203}/*}}}*/
    204 void L2ProjectionBaseAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
     204void           L2ProjectionBaseAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
    205205
    206206        int inputenum,domaintype,elementtype;
     
    225225        }
    226226}/*}}}*/
    227 void L2ProjectionBaseAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
     227void           L2ProjectionBaseAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
    228228        /*Default, do nothing*/
    229229        return;
  • issm/trunk-jpl/src/c/analyses/L2ProjectionBaseAnalysis.h

    r18057 r18930  
    1313        public:
    1414                /*Model processing*/
    15                 int  DofsPerNode(int** doflist,int domaintype,int approximation);
    16                 void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);
    17                 void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);
    18                 void CreateNodes(Nodes* nodes,IoModel* iomodel);
    1915                void CreateConstraints(Constraints* constraints,IoModel* iomodel);
    2016                void CreateLoads(Loads* loads, IoModel* iomodel);
     17                void CreateNodes(Nodes* nodes,IoModel* iomodel);
     18                int  DofsPerNode(int** doflist,int domaintype,int approximation);
     19                void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);
     20                void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);
    2121
    2222                /*Finite element Analysis*/
     
    2626                ElementMatrix* CreateKMatrix(Element* element);
    2727                ElementVector* CreatePVector(Element* element);
    28                 void GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);
    29                 void GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);
    30                 void InputUpdateFromSolution(IssmDouble* solution,Element* element);
    31                 void UpdateConstraints(FemModel* femmodel);
     28                void           GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);
     29                void           GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);
     30                void           InputUpdateFromSolution(IssmDouble* solution,Element* element);
     31                void           UpdateConstraints(FemModel* femmodel);
    3232};
    3333#endif
  • issm/trunk-jpl/src/c/analyses/L2ProjectionEPLAnalysis.cpp

    r18057 r18930  
    66
    77/*Model processing*/
     8void L2ProjectionEPLAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
     9
     10        /*No constraints*/
     11}/*}}}*/
     12void L2ProjectionEPLAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
     13
     14        /*No loads*/
     15}/*}}}*/
     16void L2ProjectionEPLAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
     17        /*Now, do we really want DC?*/
     18        int  hydrology_model;
     19        iomodel->Constant(&hydrology_model,HydrologyModelEnum);
     20        if(hydrology_model!=HydrologydcEnum) return;
     21
     22        /*Do we want an efficient layer*/
     23        bool isefficientlayer;
     24        iomodel->Constant(&isefficientlayer,HydrologydcIsefficientlayerEnum);
     25        if(!isefficientlayer) return;
     26
     27        if(iomodel->domaintype==Domain3DEnum){
     28                iomodel->FetchData(1,MeshVertexonbaseEnum);
     29        }
     30        else if(iomodel->domaintype==Domain2DverticalEnum){
     31                iomodel->FetchData(1,MeshVertexonbaseEnum);
     32        }
     33        ::CreateNodes(nodes,iomodel,L2ProjectionEPLAnalysisEnum,P1Enum);
     34        iomodel->DeleteData(1,MeshVertexonbaseEnum);
     35}/*}}}*/
    836int  L2ProjectionEPLAnalysis::DofsPerNode(int** doflist,int domaintype,int approximation){/*{{{*/
    937        return 1;
    10 }/*}}}*/
    11 void L2ProjectionEPLAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
    1238}/*}}}*/
    1339void L2ProjectionEPLAnalysis::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/
     
    4167        }
    4268}/*}}}*/
    43 void L2ProjectionEPLAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
    44         /*Now, do we really want DC?*/
    45         int  hydrology_model;
    46         iomodel->Constant(&hydrology_model,HydrologyModelEnum);
    47         if(hydrology_model!=HydrologydcEnum) return;
    48 
    49         /*Do we want an efficient layer*/
    50         bool isefficientlayer;
    51         iomodel->Constant(&isefficientlayer,HydrologydcIsefficientlayerEnum);
    52         if(!isefficientlayer) return;
    53 
    54         if(iomodel->domaintype==Domain3DEnum){
    55                 iomodel->FetchData(1,MeshVertexonbaseEnum);
    56         }
    57         else if(iomodel->domaintype==Domain2DverticalEnum){
    58                 iomodel->FetchData(1,MeshVertexonbaseEnum);
    59         }
    60         ::CreateNodes(nodes,iomodel,L2ProjectionEPLAnalysisEnum,P1Enum);
    61         iomodel->DeleteData(1,MeshVertexonbaseEnum);
    62 }/*}}}*/
    63 void L2ProjectionEPLAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
    64 
    65         /*No constraints*/
    66 }/*}}}*/
    67 void L2ProjectionEPLAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
    68 
    69         /*No loads*/
     69void L2ProjectionEPLAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
    7070}/*}}}*/
    7171
     
    226226        return pe;
    227227}/*}}}*/
    228 void L2ProjectionEPLAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
     228void           L2ProjectionEPLAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
    229229           _error_("not implemented yet");
    230230}/*}}}*/
    231 void L2ProjectionEPLAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
     231void           L2ProjectionEPLAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
    232232        _error_("Not implemented yet");
    233233}/*}}}*/
    234 void L2ProjectionEPLAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
     234void           L2ProjectionEPLAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
    235235        int inputenum,domaintype;
    236236
     
    250250        }
    251251}/*}}}*/
    252 void L2ProjectionEPLAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
     252void           L2ProjectionEPLAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
    253253        /*Default, do nothing*/
    254254        return;
  • issm/trunk-jpl/src/c/analyses/L2ProjectionEPLAnalysis.h

    r18057 r18930  
    1313        public:
    1414                /*Model processing*/
    15                 int  DofsPerNode(int** doflist,int domaintype,int approximation);
    16                 void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);
    17                 void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);
    18                 void CreateNodes(Nodes* nodes,IoModel* iomodel);
    1915                void CreateConstraints(Constraints* constraints,IoModel* iomodel);
    2016                void CreateLoads(Loads* loads, IoModel* iomodel);
     17                void CreateNodes(Nodes* nodes,IoModel* iomodel);
     18                int  DofsPerNode(int** doflist,int domaintype,int approximation);
     19                void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);
     20                void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);
    2121
    2222                /*Finite element Analysis*/
     
    2626                ElementMatrix* CreateKMatrix(Element* element);
    2727                ElementVector* CreatePVector(Element* element);
    28                 void GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);
    29                 void GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);
    30                 void InputUpdateFromSolution(IssmDouble* solution,Element* element);
    31                 void UpdateConstraints(FemModel* femmodel);
     28                void           GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);
     29                void           GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);
     30                void           InputUpdateFromSolution(IssmDouble* solution,Element* element);
     31                void           UpdateConstraints(FemModel* femmodel);
    3232};
    3333#endif
  • issm/trunk-jpl/src/c/analyses/LevelsetAnalysis.cpp

    r18862 r18930  
    1111#include "../solutionsequences/solutionsequences.h"
    1212
    13 int LevelsetAnalysis::DofsPerNode(int** doflist,int domaintype,int approximation){/*{{{*/
    14         return 1;
     13void LevelsetAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
     14        return;
    1515}
    1616/*}}}*/
    17 void LevelsetAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
     17void LevelsetAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
    1818        return;
     19}/*}}}*/
     20void LevelsetAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
     21        int finiteelement=P1Enum;
     22        if(iomodel->domaintype!=Domain2DhorizontalEnum) iomodel->FetchData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum);
     23        ::CreateNodes(nodes,iomodel,LevelsetAnalysisEnum,finiteelement);
     24        iomodel->DeleteData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum);
     25}
     26/*}}}*/
     27int  LevelsetAnalysis::DofsPerNode(int** doflist,int domaintype,int approximation){/*{{{*/
     28        return 1;
    1929}
    2030/*}}}*/
     
    6070}
    6171/*}}}*/
    62 void LevelsetAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
    63         int finiteelement=P1Enum;
    64         if(iomodel->domaintype!=Domain2DhorizontalEnum) iomodel->FetchData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum);
    65         ::CreateNodes(nodes,iomodel,LevelsetAnalysisEnum,finiteelement);
    66         iomodel->DeleteData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum);
    67 }
    68 /*}}}*/
    69 void LevelsetAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
     72void LevelsetAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
    7073        return;
    7174}
    7275/*}}}*/
    73 void LevelsetAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
    74         return;
    75 }/*}}}*/
    7676
    7777/*Finite element Analysis*/
    78 void LevelsetAnalysis::Core(FemModel* femmodel){/*{{{*/
     78void           LevelsetAnalysis::Core(FemModel* femmodel){/*{{{*/
    7979
    8080        #if !defined(_DEVELOPMENT_)
     
    404404        return pe;
    405405}/*}}}*/
    406 void LevelsetAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
     406void           LevelsetAnalysis::GetB(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
     407        /*Compute B  matrix. B=[B1 B2 B3] where Bi is of size 3*NDOF2.
     408         * For node i, Bi can be expressed in the actual coordinate system
     409         * by:
     410         *       Bi=[ N ]
     411         *          [ N ]
     412         * where N is the finiteelement function for node i.
     413         *
     414         * We assume B_prog has been allocated already, of size: 2x(NDOF1*numnodes)
     415         */
     416
     417        /*Fetch number of nodes for this finite element*/
     418        int numnodes = element->GetNumberOfNodes();
     419
     420        /*Get nodal functions*/
     421        IssmDouble* basis=xNew<IssmDouble>(numnodes);
     422        element->NodalFunctions(basis,gauss);
     423
     424        /*Build B: */
     425        for(int i=0;i<numnodes;i++){
     426                B[numnodes*0+i] = basis[i];
     427                B[numnodes*1+i] = basis[i];
     428        }
     429
     430        /*Clean-up*/
     431        xDelete<IssmDouble>(basis);
     432}/*}}}*/
     433void           LevelsetAnalysis::GetBprime(IssmDouble* Bprime,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
     434        /*Compute B'  matrix. B'=[B1' B2' B3'] where Bi' is of size 3*NDOF2.
     435         * For node i, Bi' can be expressed in the actual coordinate system
     436         * by:
     437         *       Bi_prime=[ dN/dx ]
     438         *                [ dN/dy ]
     439         * where N is the finiteelement function for node i.
     440         *
     441         * We assume B' has been allocated already, of size: 3x(NDOF2*numnodes)
     442         */
     443
     444        /*Fetch number of nodes for this finite element*/
     445        int numnodes = element->GetNumberOfNodes();
     446
     447        /*Get nodal functions derivatives*/
     448        IssmDouble* dbasis=xNew<IssmDouble>(2*numnodes);
     449        element->NodalFunctionsDerivatives(dbasis,xyz_list,gauss);
     450
     451        /*Build B': */
     452        for(int i=0;i<numnodes;i++){
     453                Bprime[numnodes*0+i] = dbasis[0*numnodes+i];
     454                Bprime[numnodes*1+i] = dbasis[1*numnodes+i];
     455        }
     456
     457        /*Clean-up*/
     458        xDelete<IssmDouble>(dbasis);
     459
     460}/*}}}*/
     461IssmDouble     LevelsetAnalysis::GetDistanceToStraight(IssmDouble* q, IssmDouble* s0, IssmDouble* s1){/*{{{*/
     462        // returns distance d of point q to straight going through points s0, s1
     463        // d=|a x b|/|b|
     464        // with a=q-s0, b=s1-s0
     465       
     466        /* Intermediaries */
     467        const int dim=2;
     468        int i;
     469        IssmDouble a[dim], b[dim];
     470        IssmDouble norm_b;
     471
     472        for(i=0;i<dim;i++){
     473                a[i]=q[i]-s0[i];
     474                b[i]=s1[i]-s0[i];
     475        }
     476       
     477        norm_b=0.;
     478        for(i=0;i<dim;i++)
     479                norm_b+=b[i]*b[i];
     480        norm_b=sqrt(norm_b);
     481        _assert_(norm_b>0.);
     482
     483        return fabs(a[0]*b[1]-a[1]*b[0])/norm_b;
     484}/*}}}*/
     485void           LevelsetAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
    407486        _error_("not implemented yet");
    408487}/*}}}*/
    409 void LevelsetAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
     488void           LevelsetAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
    410489        _error_("Not implemented yet");
    411490}/*}}}*/
    412 void LevelsetAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
     491void           LevelsetAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
    413492
    414493        int domaintype;
     
    424503        }
    425504}/*}}}*/
    426 void LevelsetAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
    427         /*Default, do nothing*/
    428         return;
    429 }/*}}}*/
    430 void LevelsetAnalysis::GetB(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
    431         /*Compute B  matrix. B=[B1 B2 B3] where Bi is of size 3*NDOF2.
    432          * For node i, Bi can be expressed in the actual coordinate system
    433          * by:
    434          *       Bi=[ N ]
    435          *          [ N ]
    436          * where N is the finiteelement function for node i.
    437          *
    438          * We assume B_prog has been allocated already, of size: 2x(NDOF1*numnodes)
    439          */
    440 
    441         /*Fetch number of nodes for this finite element*/
    442         int numnodes = element->GetNumberOfNodes();
    443 
    444         /*Get nodal functions*/
    445         IssmDouble* basis=xNew<IssmDouble>(numnodes);
    446         element->NodalFunctions(basis,gauss);
    447 
    448         /*Build B: */
    449         for(int i=0;i<numnodes;i++){
    450                 B[numnodes*0+i] = basis[i];
    451                 B[numnodes*1+i] = basis[i];
    452         }
    453 
    454         /*Clean-up*/
    455         xDelete<IssmDouble>(basis);
    456 }/*}}}*/
    457 void LevelsetAnalysis::GetBprime(IssmDouble* Bprime,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
    458         /*Compute B'  matrix. B'=[B1' B2' B3'] where Bi' is of size 3*NDOF2.
    459          * For node i, Bi' can be expressed in the actual coordinate system
    460          * by:
    461          *       Bi_prime=[ dN/dx ]
    462          *                [ dN/dy ]
    463          * where N is the finiteelement function for node i.
    464          *
    465          * We assume B' has been allocated already, of size: 3x(NDOF2*numnodes)
    466          */
    467 
    468         /*Fetch number of nodes for this finite element*/
    469         int numnodes = element->GetNumberOfNodes();
    470 
    471         /*Get nodal functions derivatives*/
    472         IssmDouble* dbasis=xNew<IssmDouble>(2*numnodes);
    473         element->NodalFunctionsDerivatives(dbasis,xyz_list,gauss);
    474 
    475         /*Build B': */
    476         for(int i=0;i<numnodes;i++){
    477                 Bprime[numnodes*0+i] = dbasis[0*numnodes+i];
    478                 Bprime[numnodes*1+i] = dbasis[1*numnodes+i];
    479         }
    480 
    481         /*Clean-up*/
    482         xDelete<IssmDouble>(dbasis);
    483 
    484 }/*}}}*/
    485 void LevelsetAnalysis::SetDistanceOnIntersectedElements(FemModel* femmodel){/*{{{*/
     505void           LevelsetAnalysis::SetDistanceOnIntersectedElements(FemModel* femmodel){/*{{{*/
    486506
    487507        /* Intermediaries */
     
    539559        delete dist_zerolevelset;
    540560}/*}}}*/
    541 void LevelsetAnalysis::SetDistanceToZeroLevelsetElement(Vector<IssmDouble>* vec_signed_dist, Element* element){/*{{{*/
     561void           LevelsetAnalysis::SetDistanceToZeroLevelsetElement(Vector<IssmDouble>* vec_signed_dist, Element* element){/*{{{*/
    542562
    543563        if(!element->IsZeroLevelset(MaskIceLevelsetEnum))
     
    592612        xDelete<IssmDouble>(xyz_list_zero);
    593613}/*}}}*/
    594 IssmDouble LevelsetAnalysis::GetDistanceToStraight(IssmDouble* q, IssmDouble* s0, IssmDouble* s1){/*{{{*/
    595         // returns distance d of point q to straight going through points s0, s1
    596         // d=|a x b|/|b|
    597         // with a=q-s0, b=s1-s0
    598        
    599         /* Intermediaries */
    600         const int dim=2;
    601         int i;
    602         IssmDouble a[dim], b[dim];
    603         IssmDouble norm_b;
    604 
    605         for(i=0;i<dim;i++){
    606                 a[i]=q[i]-s0[i];
    607                 b[i]=s1[i]-s0[i];
    608         }
    609        
    610         norm_b=0.;
    611         for(i=0;i<dim;i++)
    612                 norm_b+=b[i]*b[i];
    613         norm_b=sqrt(norm_b);
    614         _assert_(norm_b>0.);
    615 
    616         return fabs(a[0]*b[1]-a[1]*b[0])/norm_b;
    617 }/*}}}*/
     614void           LevelsetAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
     615        /*Default, do nothing*/
     616        return;
     617}/*}}}*/
  • issm/trunk-jpl/src/c/analyses/LevelsetAnalysis.h

    r18057 r18930  
    1313        public:
    1414                /*Model processing*/
    15                 int  DofsPerNode(int** doflist,int domaintype,int approximation);
    16                 void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);
    17                 void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);
    18                 void CreateNodes(Nodes* nodes,IoModel* iomodel);
    1915                void CreateConstraints(Constraints* constraints,IoModel* iomodel);
    2016                void CreateLoads(Loads* loads, IoModel* iomodel);
     17                void CreateNodes(Nodes* nodes,IoModel* iomodel);
     18                int  DofsPerNode(int** doflist,int domaintype,int approximation);
     19                void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);
     20                void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);
    2121
    2222                /*Finite element Analysis*/
     
    2626                ElementMatrix* CreateKMatrix(Element* element);
    2727                ElementVector* CreatePVector(Element* element);
    28                 void GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);
    29                 void GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);
    30                 void InputUpdateFromSolution(IssmDouble* solution,Element* element);
    31                 void UpdateConstraints(FemModel* femmodel);
    32                 void GetB(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss);
    33                 void GetBprime(IssmDouble* Bprime,Element* element,IssmDouble* xyz_list,Gauss* gauss);
    34                 void SetDistanceOnIntersectedElements(FemModel* femmodel);
    35                 void SetDistanceToZeroLevelsetElement(Vector<IssmDouble>* vec_signed_dist, Element* element);
    36                 IssmDouble GetDistanceToStraight(IssmDouble* q, IssmDouble* s0, IssmDouble* s1);
     28                void           GetB(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss);
     29                void           GetBprime(IssmDouble* Bprime,Element* element,IssmDouble* xyz_list,Gauss* gauss);
     30                IssmDouble     GetDistanceToStraight(IssmDouble* q, IssmDouble* s0, IssmDouble* s1);
     31                void           GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);
     32                void           GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);
     33                void           InputUpdateFromSolution(IssmDouble* solution,Element* element);
     34                void           SetDistanceOnIntersectedElements(FemModel* femmodel);
     35                void           SetDistanceToZeroLevelsetElement(Vector<IssmDouble>* vec_signed_dist, Element* element);
     36                void           UpdateConstraints(FemModel* femmodel);
    3737};
    3838#endif
  • issm/trunk-jpl/src/c/analyses/LsfReinitializationAnalysis.cpp

    r18521 r18930  
    1010
    1111/*Model processing*/
     12void LsfReinitializationAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
     13        /* Do nothing for now */
     14}/*}}}*/
     15void LsfReinitializationAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
     16        /* Do nothing for now */
     17}/*}}}*/
     18void LsfReinitializationAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
     19        int finiteelement=P1Enum;
     20        if(iomodel->domaintype!=Domain2DhorizontalEnum) iomodel->FetchData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum);
     21        ::CreateNodes(nodes,iomodel,LsfReinitializationAnalysisEnum,finiteelement);
     22        iomodel->DeleteData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum);
     23}/*}}}*/
    1224int  LsfReinitializationAnalysis::DofsPerNode(int** doflist,int domaintype,int approximation){/*{{{*/
    1325        return 1;
    14 }/*}}}*/
    15 void LsfReinitializationAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
    16         /* Do nothing for now */
    1726}/*}}}*/
    1827void LsfReinitializationAnalysis::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/
     
    3443        iomodel->FetchDataToInput(elements,MaskIceLevelsetEnum);
    3544}/*}}}*/
    36 void LsfReinitializationAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
    37         int finiteelement=P1Enum;
    38         if(iomodel->domaintype!=Domain2DhorizontalEnum) iomodel->FetchData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum);
    39         ::CreateNodes(nodes,iomodel,LsfReinitializationAnalysisEnum,finiteelement);
    40         iomodel->DeleteData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum);
    41 }/*}}}*/
    42 void LsfReinitializationAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
     45void LsfReinitializationAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
    4346        /* Do nothing for now */
    4447}/*}}}*/
    45 void LsfReinitializationAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
    46         /* Do nothing for now */
    47 }/*}}}*/
    4848
    4949/*Finite element Analysis*/
    50 void  LsfReinitializationAnalysis::Core(FemModel* femmodel){/*{{{*/
     50void           LsfReinitializationAnalysis::Core(FemModel* femmodel){/*{{{*/
    5151
    5252        /*parameters: */
     
    249249        return pe;
    250250        }/*}}}*/
    251 void LsfReinitializationAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
     251void           LsfReinitializationAnalysis::GetB(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
     252        /*Compute B  matrix. B=[B1 B2 B3] where Bi is of size 3*NDOF2.
     253         * For node i, Bi can be expressed in the actual coordinate system
     254         * by:
     255         *       Bi=[ N ]
     256         *          [ N ]
     257         * where N is the finiteelement function for node i.
     258         *
     259         * We assume B_prog has been allocated already, of size: 2x(NDOF1*numnodes)
     260         */
     261
     262        /*Fetch number of nodes for this finite element*/
     263        int numnodes = element->GetNumberOfNodes();
     264
     265        /*Get nodal functions*/
     266        IssmDouble* basis=xNew<IssmDouble>(numnodes);
     267        element->NodalFunctions(basis,gauss);
     268
     269        /*Build B: */
     270        for(int i=0;i<numnodes;i++){
     271                B[numnodes*0+i] = basis[i];
     272                B[numnodes*1+i] = basis[i];
     273        }
     274
     275        /*Clean-up*/
     276        xDelete<IssmDouble>(basis);
     277}/*}}}*/
     278void           LsfReinitializationAnalysis::GetBprime(IssmDouble* Bprime,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
     279        /*Compute B'  matrix. B'=[B1' B2' B3'] where Bi' is of size 3*NDOF2.
     280         * For node i, Bi' can be expressed in the actual coordinate system
     281         * by:
     282         *       Bi_prime=[ dN/dx ]
     283         *                [ dN/dy ]
     284         * where N is the finiteelement function for node i.
     285         *
     286         * We assume B' has been allocated already, of size: 3x(NDOF2*numnodes)
     287         */
     288
     289        /*Fetch number of nodes for this finite element*/
     290        int numnodes = element->GetNumberOfNodes();
     291
     292        /*Get nodal functions derivatives*/
     293        IssmDouble* dbasis=xNew<IssmDouble>(2*numnodes);
     294        element->NodalFunctionsDerivatives(dbasis,xyz_list,gauss);
     295
     296        /*Build B': */
     297        for(int i=0;i<numnodes;i++){
     298                Bprime[numnodes*0+i] = dbasis[0*numnodes+i];
     299                Bprime[numnodes*1+i] = dbasis[1*numnodes+i];
     300        }
     301
     302        /*Clean-up*/
     303        xDelete<IssmDouble>(dbasis);
     304
     305}/*}}}*/
     306IssmDouble     LsfReinitializationAnalysis::GetDistanceToStraight(IssmDouble* q, IssmDouble* s0, IssmDouble* s1){/*{{{*/
     307        // returns distance d of point q to straight going through points s0, s1
     308        // d=|a x b|/|b|
     309        // with a=q-s0, b=s1-s0
     310       
     311        /* Intermediaries */
     312        const int dim=2;
     313        int i;
     314        IssmDouble a[dim], b[dim];
     315        IssmDouble norm_b;
     316
     317        for(i=0;i<dim;i++){
     318                a[i]=q[i]-s0[i];
     319                b[i]=s1[i]-s0[i];
     320        }
     321       
     322        norm_b=0.;
     323        for(i=0;i<dim;i++)
     324                norm_b+=b[i]*b[i];
     325        norm_b=sqrt(norm_b);
     326        _assert_(norm_b>0.);
     327
     328        return fabs(a[0]*b[1]-a[1]*b[0])/norm_b;
     329}/*}}}*/
     330void           LsfReinitializationAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
    252331
    253332        IssmDouble   lsf;
     
    284363
    285364}/*}}}*/
    286 void LsfReinitializationAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
     365void           LsfReinitializationAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
    287366        _error_("Not implemented yet");
    288367}/*}}}*/
    289 void LsfReinitializationAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
     368void           LsfReinitializationAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
    290369
    291370        int domaintype;
     
    301380        }
    302381}/*}}}*/
    303 void LsfReinitializationAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
    304         /* Do nothing for now */
    305 }/*}}}*/
    306 void LsfReinitializationAnalysis::GetB(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
    307         /*Compute B  matrix. B=[B1 B2 B3] where Bi is of size 3*NDOF2.
    308          * For node i, Bi can be expressed in the actual coordinate system
    309          * by:
    310          *       Bi=[ N ]
    311          *          [ N ]
    312          * where N is the finiteelement function for node i.
    313          *
    314          * We assume B_prog has been allocated already, of size: 2x(NDOF1*numnodes)
    315          */
    316 
    317         /*Fetch number of nodes for this finite element*/
    318         int numnodes = element->GetNumberOfNodes();
    319 
    320         /*Get nodal functions*/
    321         IssmDouble* basis=xNew<IssmDouble>(numnodes);
    322         element->NodalFunctions(basis,gauss);
    323 
    324         /*Build B: */
    325         for(int i=0;i<numnodes;i++){
    326                 B[numnodes*0+i] = basis[i];
    327                 B[numnodes*1+i] = basis[i];
    328         }
    329 
    330         /*Clean-up*/
    331         xDelete<IssmDouble>(basis);
    332 }/*}}}*/
    333 void LsfReinitializationAnalysis::GetBprime(IssmDouble* Bprime,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
    334         /*Compute B'  matrix. B'=[B1' B2' B3'] where Bi' is of size 3*NDOF2.
    335          * For node i, Bi' can be expressed in the actual coordinate system
    336          * by:
    337          *       Bi_prime=[ dN/dx ]
    338          *                [ dN/dy ]
    339          * where N is the finiteelement function for node i.
    340          *
    341          * We assume B' has been allocated already, of size: 3x(NDOF2*numnodes)
    342          */
    343 
    344         /*Fetch number of nodes for this finite element*/
    345         int numnodes = element->GetNumberOfNodes();
    346 
    347         /*Get nodal functions derivatives*/
    348         IssmDouble* dbasis=xNew<IssmDouble>(2*numnodes);
    349         element->NodalFunctionsDerivatives(dbasis,xyz_list,gauss);
    350 
    351         /*Build B': */
    352         for(int i=0;i<numnodes;i++){
    353                 Bprime[numnodes*0+i] = dbasis[0*numnodes+i];
    354                 Bprime[numnodes*1+i] = dbasis[1*numnodes+i];
    355         }
    356 
    357         /*Clean-up*/
    358         xDelete<IssmDouble>(dbasis);
    359 
    360 }/*}}}*/
    361 
    362 /* Other */
    363 void LsfReinitializationAnalysis::SetReinitSPCs(FemModel* femmodel){/*{{{*/
     382bool           LsfReinitializationAnalysis::ReinitConvergence(Vector<IssmDouble>* lsfg,Vector<IssmDouble>* lsfg_old,IssmDouble reltol){/*{{{*/
     383
     384        /*Output*/
     385        bool converged = true;
     386
     387        /*Intermediary*/
     388        Vector<IssmDouble>* dlsfg    = NULL;
     389        IssmDouble          norm_dlsf,norm_lsf;
     390
     391        /*compute norm(du)/norm(u)*/
     392        dlsfg=lsfg_old->Duplicate(); lsfg_old->Copy(dlsfg); dlsfg->AYPX(lsfg,-1.0);
     393        norm_dlsf=dlsfg->Norm(NORM_TWO); norm_lsf=lsfg_old->Norm(NORM_TWO);
     394        if (xIsNan<IssmDouble>(norm_dlsf) || xIsNan<IssmDouble>(norm_lsf)) _error_("convergence criterion is NaN!");
     395        if((norm_dlsf/norm_lsf)<reltol){
     396                if(VerboseConvergence()) _printf0_("\n"<<setw(50)<<left<<"   Velocity convergence: norm(du)/norm(u)"<<norm_dlsf/norm_lsf*100<<" < "<<reltol*100<<" %\n");
     397        }
     398        else{
     399                if(VerboseConvergence()) _printf0_("\n"<<setw(50)<<left<<"   Velocity convergence: norm(du)/norm(u)"<<norm_dlsf/norm_lsf*100<<" > "<<reltol*100<<" %\n");
     400                converged=false;
     401        }
     402
     403        /*Cleanup*/
     404        delete dlsfg;
     405
     406        return converged;
     407}/*}}}*/
     408void           LsfReinitializationAnalysis::SetDistanceOnIntersectedElements(FemModel* femmodel){/*{{{*/
     409
     410        /* Intermediaries */
     411        int i;
     412        IssmDouble dmaxp,dmaxm,val;
     413        Element* element;
     414
     415        /*Initialize vector with number of vertices*/
     416        int numvertices=femmodel->vertices->NumberOfVertices();
     417
     418        Vector<IssmDouble>* vec_dist_zerolevelset = NULL;
     419        GetVectorFromInputsx(&vec_dist_zerolevelset, femmodel, MaskIceLevelsetEnum, VertexEnum);
     420       
     421        /* set distance on elements intersected by zero levelset */
     422        for(i=0;i<femmodel->elements->Size();i++){
     423                element=xDynamicCast<Element*>(femmodel->elements->GetObjectByOffset(i));
     424                if(element->IsZeroLevelset(MaskIceLevelsetEnum)){
     425                        SetDistanceToZeroLevelsetElement(vec_dist_zerolevelset, element);
     426                }
     427        }
     428        vec_dist_zerolevelset->Assemble();
     429
     430        /* Get maximum distance to interface along vertices */
     431        dmaxp=0.; dmaxm=0.;
     432        for(i=0;i<numvertices;i++){
     433                vec_dist_zerolevelset->GetValue(&val,i);
     434                if((val>0.) && (val>dmaxp))
     435                         dmaxp=val;
     436                else if((val<0.) && (val<dmaxm))
     437                         dmaxm=val;
     438        }
     439        //wait until all values are computed
     440
     441        /* set all none intersected vertices to max/min distance */
     442        for(i=0;i<numvertices;i++){
     443                vec_dist_zerolevelset->GetValue(&val,i);
     444                if(val==1.) //FIXME: improve check
     445                        vec_dist_zerolevelset->SetValue(i,3.*dmaxp,INS_VAL);
     446                else if(val==-1.)
     447                        vec_dist_zerolevelset->SetValue(i,3.*dmaxm,INS_VAL);
     448        }
     449
     450        /*Assemble vector and serialize */
     451        vec_dist_zerolevelset->Assemble();
     452        IssmDouble* dist_zerolevelset=vec_dist_zerolevelset->ToMPISerial();
     453        InputUpdateFromVectorx(femmodel,dist_zerolevelset,MaskIceLevelsetEnum,VertexSIdEnum);
     454
     455        /*Clean up and return*/
     456        delete vec_dist_zerolevelset;
     457        delete dist_zerolevelset;
     458
     459}/*}}}*/
     460void           LsfReinitializationAnalysis::SetDistanceToZeroLevelsetElement(Vector<IssmDouble>* vec_signed_dist, Element* element){/*{{{*/
     461
     462        if(!element->IsZeroLevelset(MaskIceLevelsetEnum))
     463                return;
     464
     465        /* Intermediaries */
     466        int dim=3;
     467        int i,d;
     468        IssmDouble dist,lsf_old;
     469
     470        int numvertices=element->GetNumberOfVertices();
     471
     472        IssmDouble* lsf = xNew<IssmDouble>(numvertices);
     473        IssmDouble* sign_lsf = xNew<IssmDouble>(numvertices);
     474        IssmDouble* signed_dist = xNew<IssmDouble>(numvertices);
     475        IssmDouble* s0 = xNew<IssmDouble>(dim);
     476        IssmDouble* s1 = xNew<IssmDouble>(dim);
     477        IssmDouble* v = xNew<IssmDouble>(dim);
     478        IssmDouble* xyz_list = NULL;
     479        IssmDouble* xyz_list_zero = NULL;
     480
     481        /* retrieve inputs and parameters */
     482        element->GetVerticesCoordinates(&xyz_list);
     483        element->GetInputListOnVertices(lsf,MaskIceLevelsetEnum);
     484
     485        /* get sign of levelset function */
     486        for(i=0;i<numvertices;i++)
     487                sign_lsf[i]=(lsf[i]>=0.?1.:-1.);
     488
     489        element->ZeroLevelsetCoordinates(&xyz_list_zero, xyz_list, MaskIceLevelsetEnum);
     490        for(i=0;i<dim;i++){
     491                s0[i]=xyz_list_zero[0+i];
     492                s1[i]=xyz_list_zero[3+i];
     493        }
     494
     495        /* get signed_distance of vertices to zero levelset straight */
     496        for(i=0;i<numvertices;i++){
     497                for(d=0;d<dim;d++)
     498                        v[d]=xyz_list[dim*i+d];
     499                dist=GetDistanceToStraight(&v[0],&s0[0],&s1[0]);
     500                signed_dist[i]=sign_lsf[i]*dist;
     501        }
     502       
     503        /* insert signed_distance into vec_signed_dist, if computed distance is smaller */
     504        for(i=0;i<numvertices;i++){
     505                vec_signed_dist->GetValue(&lsf_old, element->vertices[i]->Sid());
     506                /* initial lsf values are +-1. Update those fields or if distance to interface smaller.*/
     507                if(fabs(lsf_old)==1. || fabs(signed_dist[i])<fabs(lsf_old))
     508                        vec_signed_dist->SetValue(element->vertices[i]->Sid(),signed_dist[i],INS_VAL);
     509        }
     510
     511        xDelete<IssmDouble>(lsf);
     512        xDelete<IssmDouble>(sign_lsf);
     513        xDelete<IssmDouble>(signed_dist);
     514        xDelete<IssmDouble>(s0);
     515        xDelete<IssmDouble>(s1);
     516        xDelete<IssmDouble>(v);
     517
     518}/*}}}*/
     519void           LsfReinitializationAnalysis::SetReinitSPCs(FemModel* femmodel){/*{{{*/
    364520
    365521        int i,k, numnodes;
     
    399555
    400556}/*}}}*/
    401 void LsfReinitializationAnalysis::SetDistanceOnIntersectedElements(FemModel* femmodel){/*{{{*/
    402 
    403         /* Intermediaries */
    404         int i;
    405         IssmDouble dmaxp,dmaxm,val;
    406         Element* element;
    407 
    408         /*Initialize vector with number of vertices*/
    409         int numvertices=femmodel->vertices->NumberOfVertices();
    410 
    411         Vector<IssmDouble>* vec_dist_zerolevelset = NULL;
    412         GetVectorFromInputsx(&vec_dist_zerolevelset, femmodel, MaskIceLevelsetEnum, VertexEnum);
    413        
    414         /* set distance on elements intersected by zero levelset */
    415         for(i=0;i<femmodel->elements->Size();i++){
    416                 element=xDynamicCast<Element*>(femmodel->elements->GetObjectByOffset(i));
    417                 if(element->IsZeroLevelset(MaskIceLevelsetEnum)){
    418                         SetDistanceToZeroLevelsetElement(vec_dist_zerolevelset, element);
    419                 }
    420         }
    421         vec_dist_zerolevelset->Assemble();
    422 
    423         /* Get maximum distance to interface along vertices */
    424         dmaxp=0.; dmaxm=0.;
    425         for(i=0;i<numvertices;i++){
    426                 vec_dist_zerolevelset->GetValue(&val,i);
    427                 if((val>0.) && (val>dmaxp))
    428                          dmaxp=val;
    429                 else if((val<0.) && (val<dmaxm))
    430                          dmaxm=val;
    431         }
    432         //wait until all values are computed
    433 
    434         /* set all none intersected vertices to max/min distance */
    435         for(i=0;i<numvertices;i++){
    436                 vec_dist_zerolevelset->GetValue(&val,i);
    437                 if(val==1.) //FIXME: improve check
    438                         vec_dist_zerolevelset->SetValue(i,3.*dmaxp,INS_VAL);
    439                 else if(val==-1.)
    440                         vec_dist_zerolevelset->SetValue(i,3.*dmaxm,INS_VAL);
    441         }
    442 
    443         /*Assemble vector and serialize */
    444         vec_dist_zerolevelset->Assemble();
    445         IssmDouble* dist_zerolevelset=vec_dist_zerolevelset->ToMPISerial();
    446         InputUpdateFromVectorx(femmodel,dist_zerolevelset,MaskIceLevelsetEnum,VertexSIdEnum);
    447 
    448         /*Clean up and return*/
    449         delete vec_dist_zerolevelset;
    450         delete dist_zerolevelset;
    451 
    452 }/*}}}*/
    453 void LsfReinitializationAnalysis::SetDistanceToZeroLevelsetElement(Vector<IssmDouble>* vec_signed_dist, Element* element){/*{{{*/
    454 
    455         if(!element->IsZeroLevelset(MaskIceLevelsetEnum))
    456                 return;
    457 
    458         /* Intermediaries */
    459         int dim=3;
    460         int i,d;
    461         IssmDouble dist,lsf_old;
    462 
    463         int numvertices=element->GetNumberOfVertices();
    464 
    465         IssmDouble* lsf = xNew<IssmDouble>(numvertices);
    466         IssmDouble* sign_lsf = xNew<IssmDouble>(numvertices);
    467         IssmDouble* signed_dist = xNew<IssmDouble>(numvertices);
    468         IssmDouble* s0 = xNew<IssmDouble>(dim);
    469         IssmDouble* s1 = xNew<IssmDouble>(dim);
    470         IssmDouble* v = xNew<IssmDouble>(dim);
    471         IssmDouble* xyz_list = NULL;
    472         IssmDouble* xyz_list_zero = NULL;
    473 
    474         /* retrieve inputs and parameters */
    475         element->GetVerticesCoordinates(&xyz_list);
    476         element->GetInputListOnVertices(lsf,MaskIceLevelsetEnum);
    477 
    478         /* get sign of levelset function */
    479         for(i=0;i<numvertices;i++)
    480                 sign_lsf[i]=(lsf[i]>=0.?1.:-1.);
    481 
    482         element->ZeroLevelsetCoordinates(&xyz_list_zero, xyz_list, MaskIceLevelsetEnum);
    483         for(i=0;i<dim;i++){
    484                 s0[i]=xyz_list_zero[0+i];
    485                 s1[i]=xyz_list_zero[3+i];
    486         }
    487 
    488         /* get signed_distance of vertices to zero levelset straight */
    489         for(i=0;i<numvertices;i++){
    490                 for(d=0;d<dim;d++)
    491                         v[d]=xyz_list[dim*i+d];
    492                 dist=GetDistanceToStraight(&v[0],&s0[0],&s1[0]);
    493                 signed_dist[i]=sign_lsf[i]*dist;
    494         }
    495        
    496         /* insert signed_distance into vec_signed_dist, if computed distance is smaller */
    497         for(i=0;i<numvertices;i++){
    498                 vec_signed_dist->GetValue(&lsf_old, element->vertices[i]->Sid());
    499                 /* initial lsf values are +-1. Update those fields or if distance to interface smaller.*/
    500                 if(fabs(lsf_old)==1. || fabs(signed_dist[i])<fabs(lsf_old))
    501                         vec_signed_dist->SetValue(element->vertices[i]->Sid(),signed_dist[i],INS_VAL);
    502         }
    503 
    504         xDelete<IssmDouble>(lsf);
    505         xDelete<IssmDouble>(sign_lsf);
    506         xDelete<IssmDouble>(signed_dist);
    507         xDelete<IssmDouble>(s0);
    508         xDelete<IssmDouble>(s1);
    509         xDelete<IssmDouble>(v);
    510 
    511 }/*}}}*/
    512 IssmDouble LsfReinitializationAnalysis::GetDistanceToStraight(IssmDouble* q, IssmDouble* s0, IssmDouble* s1){/*{{{*/
    513         // returns distance d of point q to straight going through points s0, s1
    514         // d=|a x b|/|b|
    515         // with a=q-s0, b=s1-s0
    516        
    517         /* Intermediaries */
    518         const int dim=2;
    519         int i;
    520         IssmDouble a[dim], b[dim];
    521         IssmDouble norm_b;
    522 
    523         for(i=0;i<dim;i++){
    524                 a[i]=q[i]-s0[i];
    525                 b[i]=s1[i]-s0[i];
    526         }
    527        
    528         norm_b=0.;
    529         for(i=0;i<dim;i++)
    530                 norm_b+=b[i]*b[i];
    531         norm_b=sqrt(norm_b);
    532         _assert_(norm_b>0.);
    533 
    534         return fabs(a[0]*b[1]-a[1]*b[0])/norm_b;
    535 }/*}}}*/
    536 bool LsfReinitializationAnalysis::ReinitConvergence(Vector<IssmDouble>* lsfg,Vector<IssmDouble>* lsfg_old,IssmDouble reltol){/*{{{*/
    537 
    538         /*Output*/
    539         bool converged = true;
    540 
    541         /*Intermediary*/
    542         Vector<IssmDouble>* dlsfg    = NULL;
    543         IssmDouble          norm_dlsf,norm_lsf;
    544 
    545         /*compute norm(du)/norm(u)*/
    546         dlsfg=lsfg_old->Duplicate(); lsfg_old->Copy(dlsfg); dlsfg->AYPX(lsfg,-1.0);
    547         norm_dlsf=dlsfg->Norm(NORM_TWO); norm_lsf=lsfg_old->Norm(NORM_TWO);
    548         if (xIsNan<IssmDouble>(norm_dlsf) || xIsNan<IssmDouble>(norm_lsf)) _error_("convergence criterion is NaN!");
    549         if((norm_dlsf/norm_lsf)<reltol){
    550                 if(VerboseConvergence()) _printf0_("\n"<<setw(50)<<left<<"   Velocity convergence: norm(du)/norm(u)"<<norm_dlsf/norm_lsf*100<<" < "<<reltol*100<<" %\n");
    551         }
    552         else{
    553                 if(VerboseConvergence()) _printf0_("\n"<<setw(50)<<left<<"   Velocity convergence: norm(du)/norm(u)"<<norm_dlsf/norm_lsf*100<<" > "<<reltol*100<<" %\n");
    554                 converged=false;
    555         }
    556 
    557         /*Cleanup*/
    558         delete dlsfg;
    559 
    560         return converged;
    561 }/*}}}*/
     557void           LsfReinitializationAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
     558        /* Do nothing for now */
     559}/*}}}*/
  • issm/trunk-jpl/src/c/analyses/LsfReinitializationAnalysis.h

    r18057 r18930  
    1313public:
    1414        /*Model processing*/
    15         int  DofsPerNode(int** doflist,int domaintype,int approximation);
    16         void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);
    17         void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);
    18         void CreateNodes(Nodes* nodes,IoModel* iomodel);
    1915        void CreateConstraints(Constraints* constraints,IoModel* iomodel);
    2016        void CreateLoads(Loads* loads, IoModel* iomodel);
     17        void CreateNodes(Nodes* nodes,IoModel* iomodel);
     18        int  DofsPerNode(int** doflist,int domaintype,int approximation);
     19        void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);
     20        void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);
    2121
    2222        /*Finite element Analysis*/
     
    2626        ElementMatrix* CreateKMatrix(Element* element);
    2727        ElementVector* CreatePVector(Element* element);
    28                 void GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);
    29                 void GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);
    30         void InputUpdateFromSolution(IssmDouble* solution,Element* element);
    31         void UpdateConstraints(FemModel* femmodel);
    32         void GetB(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss);
    33         void GetBprime(IssmDouble* Bprime,Element* element,IssmDouble* xyz_list,Gauss* gauss);
    34        
    35         /* Other */
    36         void SetReinitSPCs(FemModel* femmodel);
    37         void SetDistanceOnIntersectedElements(FemModel* femmodel);
    38         void SetDistanceToZeroLevelsetElement(Vector<IssmDouble>* vec_dist, Element* element);
    39         IssmDouble GetDistanceToStraight(IssmDouble* q, IssmDouble* s0, IssmDouble* s1);
    40         bool ReinitConvergence(Vector<IssmDouble>* lsfg,Vector<IssmDouble>* lsfg_old,IssmDouble reltol);
     28        void           GetB(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss);
     29        void           GetBprime(IssmDouble* Bprime,Element* element,IssmDouble* xyz_list,Gauss* gauss);
     30        IssmDouble     GetDistanceToStraight(IssmDouble* q, IssmDouble* s0, IssmDouble* s1);
     31        void           GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);
     32        void           GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);
     33        void           InputUpdateFromSolution(IssmDouble* solution,Element* element);
     34        bool           ReinitConvergence(Vector<IssmDouble>* lsfg,Vector<IssmDouble>* lsfg_old,IssmDouble reltol);
     35        void           SetDistanceOnIntersectedElements(FemModel* femmodel);
     36        void           SetDistanceToZeroLevelsetElement(Vector<IssmDouble>* vec_dist, Element* element);
     37        void           SetReinitSPCs(FemModel* femmodel);
     38        void           UpdateConstraints(FemModel* femmodel);
    4139};
    4240#endif
  • issm/trunk-jpl/src/c/analyses/MasstransportAnalysis.cpp

    r18521 r18930  
    66
    77/*Model processing*/
     8void MasstransportAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
     9
     10        /*Fetch parameters: */
     11        int stabilization;
     12        iomodel->Constant(&stabilization,MasstransportStabilizationEnum);
     13
     14        /*Do not add constraints in DG,  they are weakly imposed*/
     15        if(stabilization!=3){
     16                IoModelToConstraintsx(constraints,iomodel,MasstransportSpcthicknessEnum,MasstransportAnalysisEnum,P1Enum);
     17        }
     18
     19        /*FCT, constraints are imposed using penalties*/
     20        if(stabilization==4){
     21                constraints->ActivatePenaltyMethod(MasstransportAnalysisEnum);
     22        }
     23}/*}}}*/
     24void MasstransportAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
     25
     26        /*Intermediaries*/
     27        int element;
     28        int penpair_ids[2];
     29        int count=0;
     30        int stabilization;
     31        int numvertex_pairing;
     32
     33        /*Fetch parameters: */
     34        iomodel->Constant(&stabilization,MasstransportStabilizationEnum);
     35
     36        /*Loads only in DG*/
     37        if (stabilization==3){
     38
     39                /*Get faces and elements*/
     40                CreateFaces(iomodel);
     41                iomodel->FetchData(1,ThicknessEnum);
     42
     43                /*First load data:*/
     44                for(int i=0;i<iomodel->numberoffaces;i++){
     45
     46                        /*Get left and right elements*/
     47                        element=iomodel->faces[4*i+2]-1; //faces are [node1 node2 elem1 elem2]
     48
     49                        /*Now, if this element is not in the partition, pass: */
     50                        if(!iomodel->my_elements[element]) continue;
     51
     52                        /* Add load */
     53                        loads->AddObject(new Numericalflux(iomodel->loadcounter+i+1,i,i,iomodel,MasstransportAnalysisEnum));
     54                }
     55
     56                /*Free data: */
     57                iomodel->DeleteData(1,ThicknessEnum);
     58        }
     59
     60        /*Create Penpair for vertex_pairing: */
     61        IssmDouble *vertex_pairing=NULL;
     62        IssmDouble *nodeonbase=NULL;
     63        iomodel->FetchData(&vertex_pairing,&numvertex_pairing,NULL,MasstransportVertexPairingEnum);
     64        if(iomodel->domaintype!=Domain2DhorizontalEnum) iomodel->FetchData(&nodeonbase,NULL,NULL,MeshVertexonbaseEnum);
     65
     66        for(int i=0;i<numvertex_pairing;i++){
     67
     68                if(iomodel->my_vertices[reCast<int>(vertex_pairing[2*i+0])-1]){
     69
     70                        /*In debugging mode, check that the second node is in the same cpu*/
     71                        _assert_(iomodel->my_vertices[reCast<int>(vertex_pairing[2*i+1])-1]);
     72
     73                        /*Skip if one of the two is not on the bed*/
     74                        if(iomodel->domaintype!=Domain2DhorizontalEnum){
     75                                if(!(reCast<bool>(nodeonbase[reCast<int>(vertex_pairing[2*i+0])-1])) || !(reCast<bool>(nodeonbase[reCast<int>(vertex_pairing[2*i+1])-1]))) continue;
     76                        }
     77
     78                        /*Get node ids*/
     79                        penpair_ids[0]=iomodel->nodecounter+reCast<int>(vertex_pairing[2*i+0]);
     80                        penpair_ids[1]=iomodel->nodecounter+reCast<int>(vertex_pairing[2*i+1]);
     81
     82                        /*Create Load*/
     83                        loads->AddObject(new Penpair(
     84                                                        iomodel->loadcounter+count+1,
     85                                                        &penpair_ids[0],
     86                                                        MasstransportAnalysisEnum));
     87                        count++;
     88                }
     89        }
     90
     91        /*free ressources: */
     92        iomodel->DeleteData(vertex_pairing,MasstransportVertexPairingEnum);
     93        iomodel->DeleteData(nodeonbase,MeshVertexonbaseEnum);
     94
     95}/*}}}*/
     96void MasstransportAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
     97
     98        /*Fetch parameters: */
     99        int  stabilization;
     100        iomodel->Constant(&stabilization,MasstransportStabilizationEnum);
     101
     102        /*Check in 3d*/
     103        if(stabilization==3 && iomodel->domaintype==Domain3DEnum) _error_("DG 3d not implemented yet");
     104
     105        /*Create Nodes either DG or CG depending on stabilization*/
     106        if(iomodel->domaintype!=Domain2DhorizontalEnum) iomodel->FetchData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum);
     107        if(stabilization!=3){
     108                ::CreateNodes(nodes,iomodel,MasstransportAnalysisEnum,P1Enum);
     109        }
     110        else{
     111                ::CreateNodes(nodes,iomodel,MasstransportAnalysisEnum,P1DGEnum);
     112        }
     113        iomodel->DeleteData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum);
     114}/*}}}*/
    8115int  MasstransportAnalysis::DofsPerNode(int** doflist,int domaintype,int approximation){/*{{{*/
    9116        return 1;
    10 }/*}}}*/
    11 void MasstransportAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
    12 
    13         int     numoutputs;
    14         char**  requestedoutputs = NULL;
    15 
    16         parameters->AddObject(iomodel->CopyConstantObject(FlowequationIsFSEnum));
    17         parameters->AddObject(iomodel->CopyConstantObject(MasstransportIsfreesurfaceEnum));
    18         parameters->AddObject(iomodel->CopyConstantObject(MasstransportHydrostaticAdjustmentEnum));
    19         parameters->AddObject(iomodel->CopyConstantObject(MasstransportStabilizationEnum));
    20         parameters->AddObject(iomodel->CopyConstantObject(MasstransportMinThicknessEnum));
    21         parameters->AddObject(iomodel->CopyConstantObject(MasstransportPenaltyFactorEnum));
    22 
    23         iomodel->FetchData(&requestedoutputs,&numoutputs,MasstransportRequestedOutputsEnum);
    24         parameters->AddObject(new IntParam(MasstransportNumRequestedOutputsEnum,numoutputs));
    25         if(numoutputs)parameters->AddObject(new StringArrayParam(MasstransportRequestedOutputsEnum,requestedoutputs,numoutputs));
    26         iomodel->DeleteData(&requestedoutputs,numoutputs,MasstransportRequestedOutputsEnum);
    27 
    28117}/*}}}*/
    29118void MasstransportAnalysis::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/
     
    126215
    127216}/*}}}*/
    128 void MasstransportAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
    129 
    130         /*Fetch parameters: */
    131         int  stabilization;
    132         iomodel->Constant(&stabilization,MasstransportStabilizationEnum);
    133 
    134         /*Check in 3d*/
    135         if(stabilization==3 && iomodel->domaintype==Domain3DEnum) _error_("DG 3d not implemented yet");
    136 
    137         /*Create Nodes either DG or CG depending on stabilization*/
    138         if(iomodel->domaintype!=Domain2DhorizontalEnum) iomodel->FetchData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum);
    139         if(stabilization!=3){
    140                 ::CreateNodes(nodes,iomodel,MasstransportAnalysisEnum,P1Enum);
    141         }
    142         else{
    143                 ::CreateNodes(nodes,iomodel,MasstransportAnalysisEnum,P1DGEnum);
    144         }
    145         iomodel->DeleteData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum);
    146 }/*}}}*/
    147 void MasstransportAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
    148 
    149         /*Fetch parameters: */
    150         int stabilization;
    151         iomodel->Constant(&stabilization,MasstransportStabilizationEnum);
    152 
    153         /*Do not add constraints in DG,  they are weakly imposed*/
    154         if(stabilization!=3){
    155                 IoModelToConstraintsx(constraints,iomodel,MasstransportSpcthicknessEnum,MasstransportAnalysisEnum,P1Enum);
    156         }
    157 
    158         /*FCT, constraints are imposed using penalties*/
    159         if(stabilization==4){
    160                 constraints->ActivatePenaltyMethod(MasstransportAnalysisEnum);
    161         }
    162 }/*}}}*/
    163 void MasstransportAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
    164 
    165         /*Intermediaries*/
    166         int element;
    167         int penpair_ids[2];
    168         int count=0;
    169         int stabilization;
    170         int numvertex_pairing;
    171 
    172         /*Fetch parameters: */
    173         iomodel->Constant(&stabilization,MasstransportStabilizationEnum);
    174 
    175         /*Loads only in DG*/
    176         if (stabilization==3){
    177 
    178                 /*Get faces and elements*/
    179                 CreateFaces(iomodel);
    180                 iomodel->FetchData(1,ThicknessEnum);
    181 
    182                 /*First load data:*/
    183                 for(int i=0;i<iomodel->numberoffaces;i++){
    184 
    185                         /*Get left and right elements*/
    186                         element=iomodel->faces[4*i+2]-1; //faces are [node1 node2 elem1 elem2]
    187 
    188                         /*Now, if this element is not in the partition, pass: */
    189                         if(!iomodel->my_elements[element]) continue;
    190 
    191                         /* Add load */
    192                         loads->AddObject(new Numericalflux(iomodel->loadcounter+i+1,i,i,iomodel,MasstransportAnalysisEnum));
    193                 }
    194 
    195                 /*Free data: */
    196                 iomodel->DeleteData(1,ThicknessEnum);
    197         }
    198 
    199         /*Create Penpair for vertex_pairing: */
    200         IssmDouble *vertex_pairing=NULL;
    201         IssmDouble *nodeonbase=NULL;
    202         iomodel->FetchData(&vertex_pairing,&numvertex_pairing,NULL,MasstransportVertexPairingEnum);
    203         if(iomodel->domaintype!=Domain2DhorizontalEnum) iomodel->FetchData(&nodeonbase,NULL,NULL,MeshVertexonbaseEnum);
    204 
    205         for(int i=0;i<numvertex_pairing;i++){
    206 
    207                 if(iomodel->my_vertices[reCast<int>(vertex_pairing[2*i+0])-1]){
    208 
    209                         /*In debugging mode, check that the second node is in the same cpu*/
    210                         _assert_(iomodel->my_vertices[reCast<int>(vertex_pairing[2*i+1])-1]);
    211 
    212                         /*Skip if one of the two is not on the bed*/
    213                         if(iomodel->domaintype!=Domain2DhorizontalEnum){
    214                                 if(!(reCast<bool>(nodeonbase[reCast<int>(vertex_pairing[2*i+0])-1])) || !(reCast<bool>(nodeonbase[reCast<int>(vertex_pairing[2*i+1])-1]))) continue;
    215                         }
    216 
    217                         /*Get node ids*/
    218                         penpair_ids[0]=iomodel->nodecounter+reCast<int>(vertex_pairing[2*i+0]);
    219                         penpair_ids[1]=iomodel->nodecounter+reCast<int>(vertex_pairing[2*i+1]);
    220 
    221                         /*Create Load*/
    222                         loads->AddObject(new Penpair(
    223                                                         iomodel->loadcounter+count+1,
    224                                                         &penpair_ids[0],
    225                                                         MasstransportAnalysisEnum));
    226                         count++;
    227                 }
    228         }
    229 
    230         /*free ressources: */
    231         iomodel->DeleteData(vertex_pairing,MasstransportVertexPairingEnum);
    232         iomodel->DeleteData(nodeonbase,MeshVertexonbaseEnum);
     217void MasstransportAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
     218
     219        int     numoutputs;
     220        char**  requestedoutputs = NULL;
     221
     222        parameters->AddObject(iomodel->CopyConstantObject(FlowequationIsFSEnum));
     223        parameters->AddObject(iomodel->CopyConstantObject(MasstransportIsfreesurfaceEnum));
     224        parameters->AddObject(iomodel->CopyConstantObject(MasstransportHydrostaticAdjustmentEnum));
     225        parameters->AddObject(iomodel->CopyConstantObject(MasstransportStabilizationEnum));
     226        parameters->AddObject(iomodel->CopyConstantObject(MasstransportMinThicknessEnum));
     227        parameters->AddObject(iomodel->CopyConstantObject(MasstransportPenaltyFactorEnum));
     228
     229        iomodel->FetchData(&requestedoutputs,&numoutputs,MasstransportRequestedOutputsEnum);
     230        parameters->AddObject(new IntParam(MasstransportNumRequestedOutputsEnum,numoutputs));
     231        if(numoutputs)parameters->AddObject(new StringArrayParam(MasstransportRequestedOutputsEnum,requestedoutputs,numoutputs));
     232        iomodel->DeleteData(&requestedoutputs,numoutputs,MasstransportRequestedOutputsEnum);
    233233
    234234}/*}}}*/
     
    625625        return pe;
    626626}/*}}}*/
    627 void MasstransportAnalysis::GetB(IssmDouble* B,Element* element,int dim,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
     627void           MasstransportAnalysis::GetB(IssmDouble* B,Element* element,int dim,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
    628628        /*Compute B  matrix. B=[B1 B2 B3] where Bi is of size 3*NDOF2.
    629629         * For node i, Bi can be expressed in the actual coordinate system
     
    653653        xDelete<IssmDouble>(basis);
    654654}/*}}}*/
    655 void MasstransportAnalysis::GetBprime(IssmDouble* Bprime,Element* element,int dim,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
     655void           MasstransportAnalysis::GetBprime(IssmDouble* Bprime,Element* element,int dim,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
    656656        /*Compute B'  matrix. B'=[B1' B2' B3'] where Bi' is of size 3*NDOF2.
    657657         * For node i, Bi' can be expressed in the actual coordinate system
     
    682682
    683683}/*}}}*/
    684 void MasstransportAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
     684void           MasstransportAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
    685685        element->GetSolutionFromInputsOneDof(solution,ThicknessEnum);
    686686}/*}}}*/
    687 void MasstransportAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
     687void           MasstransportAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
    688688        _error_("Not implemented yet");
    689689}/*}}}*/
    690 void MasstransportAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
     690void           MasstransportAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
    691691
    692692        int        i,hydroadjustment,domaintype;
     
    772772        if(domaintype!=Domain2DhorizontalEnum){basalelement->DeleteMaterials(); delete basalelement;};
    773773}/*}}}*/
    774 void MasstransportAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
     774void           MasstransportAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
    775775
    776776        bool islevelset;
     
    783783
    784784/*Flux Correction Transport*/
     785ElementMatrix* MasstransportAnalysis::CreateFctKMatrix(Element* element){/*{{{*/
     786
     787        /* Check if ice in element */
     788        if(!element->IsIceInElement()) return NULL;
     789
     790        /*Intermediaries */
     791        IssmDouble Jdet;
     792        IssmDouble vx,vy;
     793        IssmDouble* xyz_list = NULL;
     794
     795        /*Fetch number of nodes and dof for this finite element*/
     796        int numnodes = element->GetNumberOfNodes();
     797        int dim      = 2;
     798
     799        /*Initialize Element vector and other vectors*/
     800        ElementMatrix* Ke     = element->NewElementMatrix();
     801        IssmDouble*    B      = xNew<IssmDouble>(dim*numnodes);
     802        IssmDouble*    Bprime = xNew<IssmDouble>(dim*numnodes);
     803        IssmDouble*    D      = xNewZeroInit<IssmDouble>(dim*dim);
     804
     805        /*Retrieve all inputs and parameters*/
     806        element->GetVerticesCoordinates(&xyz_list);
     807        Input* vxaverage_input=element->GetInput(VxEnum); _assert_(vxaverage_input);
     808        Input* vyaverage_input=element->GetInput(VyEnum); _assert_(vyaverage_input);
     809
     810        /* Start  looping on the number of gaussian points: */
     811        Gauss* gauss=element->NewGauss(2);
     812        for(int ig=gauss->begin();ig<gauss->end();ig++){
     813                gauss->GaussPoint(ig);
     814
     815                element->JacobianDeterminant(&Jdet,xyz_list,gauss);
     816                GetB(B,element,dim,xyz_list,gauss);
     817                GetBprime(Bprime,element,dim,xyz_list,gauss);
     818                vxaverage_input->GetInputValue(&vx,gauss);
     819                vyaverage_input->GetInputValue(&vy,gauss);
     820
     821                D[0*dim+0] = -gauss->weight*vx*Jdet;
     822                D[1*dim+1] = -gauss->weight*vy*Jdet;
     823
     824                TripleMultiply(B,dim,numnodes,1,
     825                                        D,dim,dim,0,
     826                                        Bprime,dim,numnodes,0,
     827                                        &Ke->values[0],1);
     828
     829        }
     830
     831        /*Clean up and return*/
     832        xDelete<IssmDouble>(xyz_list);
     833        xDelete<IssmDouble>(B);
     834        xDelete<IssmDouble>(Bprime);
     835        xDelete<IssmDouble>(D);
     836        delete gauss;
     837        return Ke;
     838}/*}}}*/
     839ElementMatrix* MasstransportAnalysis::CreateMassMatrix(Element* element){/*{{{*/
     840
     841        /* Check if ice in element */
     842        if(!element->IsIceInElement()) return NULL;
     843
     844        /*Intermediaries*/
     845        IssmDouble  D,Jdet;
     846        IssmDouble* xyz_list = NULL;
     847
     848        /*Fetch number of nodes and dof for this finite element*/
     849        int numnodes = element->GetNumberOfNodes();
     850
     851        /*Initialize Element vector and other vectors*/
     852        ElementMatrix* Me     = element->NewElementMatrix();
     853        IssmDouble*    basis  = xNew<IssmDouble>(numnodes);
     854
     855        /*Retrieve all inputs and parameters*/
     856        element->GetVerticesCoordinates(&xyz_list);
     857
     858        /* Start  looping on the number of gaussian points: */
     859        Gauss* gauss=element->NewGauss(2);
     860        for(int ig=gauss->begin();ig<gauss->end();ig++){
     861                gauss->GaussPoint(ig);
     862
     863                element->JacobianDeterminant(&Jdet,xyz_list,gauss);
     864                element->NodalFunctions(basis,gauss);
     865
     866                D=gauss->weight*Jdet;
     867                TripleMultiply(basis,1,numnodes,1,
     868                                        &D,1,1,0,
     869                                        basis,1,numnodes,0,
     870                                        &Me->values[0],1);
     871        }
     872
     873        /*Clean up and return*/
     874        xDelete<IssmDouble>(xyz_list);
     875        xDelete<IssmDouble>(basis);
     876        delete gauss;
     877        return Me;
     878}/*}}}*/
     879void           MasstransportAnalysis::FctKMatrix(Matrix<IssmDouble>** pKff,Matrix<IssmDouble>** pKfs,FemModel* femmodel){/*{{{*/
     880
     881        /*Output*/
     882        Matrix<IssmDouble>* Kff = NULL;
     883        Matrix<IssmDouble>* Kfs = NULL;
     884
     885        /*Initialize Jacobian Matrix*/
     886        AllocateSystemMatricesx(&Kff,&Kfs,NULL,NULL,femmodel);
     887
     888        /*Create and assemble matrix*/
     889        for(int i=0;i<femmodel->elements->Size();i++){
     890                Element*       element = xDynamicCast<Element*>(femmodel->elements->GetObjectByOffset(i));
     891                ElementMatrix* Ke     = this->CreateFctKMatrix(element);
     892                if(Ke) Ke->AddToGlobal(Kff,Kfs);
     893                delete Ke;
     894        }
     895        Kff->Assemble();
     896        Kfs->Assemble();
     897
     898        /*Assign output pointer*/
     899        *pKff=Kff;
     900        if(pKfs){
     901                *pKfs=Kfs;
     902        }
     903        else{
     904                delete Kfs;
     905        }
     906}/*}}}*/
    785907void           MasstransportAnalysis::LumpedMassMatrix(Vector<IssmDouble>** pMlff,FemModel* femmodel){/*{{{*/
    786908
     
    829951        *pMff=Mff;
    830952}/*}}}*/
    831 ElementMatrix* MasstransportAnalysis::CreateMassMatrix(Element* element){/*{{{*/
    832 
    833         /* Check if ice in element */
    834         if(!element->IsIceInElement()) return NULL;
    835 
    836         /*Intermediaries*/
    837         IssmDouble  D,Jdet;
    838         IssmDouble* xyz_list = NULL;
    839 
    840         /*Fetch number of nodes and dof for this finite element*/
    841         int numnodes = element->GetNumberOfNodes();
    842 
    843         /*Initialize Element vector and other vectors*/
    844         ElementMatrix* Me     = element->NewElementMatrix();
    845         IssmDouble*    basis  = xNew<IssmDouble>(numnodes);
    846 
    847         /*Retrieve all inputs and parameters*/
    848         element->GetVerticesCoordinates(&xyz_list);
    849 
    850         /* Start  looping on the number of gaussian points: */
    851         Gauss* gauss=element->NewGauss(2);
    852         for(int ig=gauss->begin();ig<gauss->end();ig++){
    853                 gauss->GaussPoint(ig);
    854 
    855                 element->JacobianDeterminant(&Jdet,xyz_list,gauss);
    856                 element->NodalFunctions(basis,gauss);
    857 
    858                 D=gauss->weight*Jdet;
    859                 TripleMultiply(basis,1,numnodes,1,
    860                                         &D,1,1,0,
    861                                         basis,1,numnodes,0,
    862                                         &Me->values[0],1);
    863         }
    864 
    865         /*Clean up and return*/
    866         xDelete<IssmDouble>(xyz_list);
    867         xDelete<IssmDouble>(basis);
    868         delete gauss;
    869         return Me;
    870 }/*}}}*/
    871 void           MasstransportAnalysis::FctKMatrix(Matrix<IssmDouble>** pKff,Matrix<IssmDouble>** pKfs,FemModel* femmodel){/*{{{*/
    872 
    873         /*Output*/
    874         Matrix<IssmDouble>* Kff = NULL;
    875         Matrix<IssmDouble>* Kfs = NULL;
    876 
    877         /*Initialize Jacobian Matrix*/
    878         AllocateSystemMatricesx(&Kff,&Kfs,NULL,NULL,femmodel);
    879 
    880         /*Create and assemble matrix*/
    881         for(int i=0;i<femmodel->elements->Size();i++){
    882                 Element*       element = xDynamicCast<Element*>(femmodel->elements->GetObjectByOffset(i));
    883                 ElementMatrix* Ke     = this->CreateFctKMatrix(element);
    884                 if(Ke) Ke->AddToGlobal(Kff,Kfs);
    885                 delete Ke;
    886         }
    887         Kff->Assemble();
    888         Kfs->Assemble();
    889 
    890         /*Assign output pointer*/
    891         *pKff=Kff;
    892         if(pKfs){
    893                 *pKfs=Kfs;
    894         }
    895         else{
    896                 delete Kfs;
    897         }
    898 }/*}}}*/
    899 ElementMatrix* MasstransportAnalysis::CreateFctKMatrix(Element* element){/*{{{*/
    900 
    901         /* Check if ice in element */
    902         if(!element->IsIceInElement()) return NULL;
    903 
    904         /*Intermediaries */
    905         IssmDouble Jdet;
    906         IssmDouble vx,vy;
    907         IssmDouble* xyz_list = NULL;
    908 
    909         /*Fetch number of nodes and dof for this finite element*/
    910         int numnodes = element->GetNumberOfNodes();
    911         int dim      = 2;
    912 
    913         /*Initialize Element vector and other vectors*/
    914         ElementMatrix* Ke     = element->NewElementMatrix();
    915         IssmDouble*    B      = xNew<IssmDouble>(dim*numnodes);
    916         IssmDouble*    Bprime = xNew<IssmDouble>(dim*numnodes);
    917         IssmDouble*    D      = xNewZeroInit<IssmDouble>(dim*dim);
    918 
    919         /*Retrieve all inputs and parameters*/
    920         element->GetVerticesCoordinates(&xyz_list);
    921         Input* vxaverage_input=element->GetInput(VxEnum); _assert_(vxaverage_input);
    922         Input* vyaverage_input=element->GetInput(VyEnum); _assert_(vyaverage_input);
    923 
    924         /* Start  looping on the number of gaussian points: */
    925         Gauss* gauss=element->NewGauss(2);
    926         for(int ig=gauss->begin();ig<gauss->end();ig++){
    927                 gauss->GaussPoint(ig);
    928 
    929                 element->JacobianDeterminant(&Jdet,xyz_list,gauss);
    930                 GetB(B,element,dim,xyz_list,gauss);
    931                 GetBprime(Bprime,element,dim,xyz_list,gauss);
    932                 vxaverage_input->GetInputValue(&vx,gauss);
    933                 vyaverage_input->GetInputValue(&vy,gauss);
    934 
    935                 D[0*dim+0] = -gauss->weight*vx*Jdet;
    936                 D[1*dim+1] = -gauss->weight*vy*Jdet;
    937 
    938                 TripleMultiply(B,dim,numnodes,1,
    939                                         D,dim,dim,0,
    940                                         Bprime,dim,numnodes,0,
    941                                         &Ke->values[0],1);
    942 
    943         }
    944 
    945         /*Clean up and return*/
    946         xDelete<IssmDouble>(xyz_list);
    947         xDelete<IssmDouble>(B);
    948         xDelete<IssmDouble>(Bprime);
    949         xDelete<IssmDouble>(D);
    950         delete gauss;
    951         return Ke;
    952 }/*}}}*/
  • issm/trunk-jpl/src/c/analyses/MasstransportAnalysis.h

    r18345 r18930  
    1313        public:
    1414                /*Model processing*/
    15                 int  DofsPerNode(int** doflist,int domaintype,int approximation);
    16                 void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);
    17                 void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);
    18                 void CreateNodes(Nodes* nodes,IoModel* iomodel);
    1915                void CreateConstraints(Constraints* constraints,IoModel* iomodel);
    2016                void CreateLoads(Loads* loads, IoModel* iomodel);
     17                void CreateNodes(Nodes* nodes,IoModel* iomodel);
     18                int  DofsPerNode(int** doflist,int domaintype,int approximation);
     19                void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);
     20                void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);
    2121
    2222                /*Finite element Analysis*/
     
    3030                ElementVector* CreatePVectorCG(Element* element);
    3131                ElementVector* CreatePVectorDG(Element* element);
    32                 void GetB(IssmDouble* B,Element* element,int dim,IssmDouble* xyz_list,Gauss* gauss);
    33                 void GetBprime(IssmDouble* B,Element* element,int dim,IssmDouble* xyz_list,Gauss* gauss);
    34                 void GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);
    35                 void GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);
    36                 void InputUpdateFromSolution(IssmDouble* solution,Element* element);
    37                 void UpdateConstraints(FemModel* femmodel);
     32                void           GetB(IssmDouble* B,Element* element,int dim,IssmDouble* xyz_list,Gauss* gauss);
     33                void           GetBprime(IssmDouble* B,Element* element,int dim,IssmDouble* xyz_list,Gauss* gauss);
     34                void           GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);
     35                void           GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);
     36                void           InputUpdateFromSolution(IssmDouble* solution,Element* element);
     37                void           UpdateConstraints(FemModel* femmodel);
    3838
    3939                /*FCT*/
     40                ElementMatrix* CreateFctKMatrix(Element* element);
     41                ElementMatrix* CreateMassMatrix(Element* element);
     42                void           FctKMatrix(Matrix<IssmDouble>** pKff,Matrix<IssmDouble>** pKfs,FemModel* femmodel);
    4043                void           LumpedMassMatrix(Vector<IssmDouble>** pMLff,FemModel* femmodel);
    4144                void           MassMatrix(Matrix<IssmDouble>** pMff,FemModel* femmodel);
    42                 void           FctKMatrix(Matrix<IssmDouble>** pKff,Matrix<IssmDouble>** pKfs,FemModel* femmodel);
    43                 ElementMatrix* CreateMassMatrix(Element* element);
    44                 ElementMatrix* CreateFctKMatrix(Element* element);
    4545};
    4646#endif
  • issm/trunk-jpl/src/c/analyses/MeltingAnalysis.cpp

    r18729 r18930  
    66
    77/*Model processing*/
     8void MeltingAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
     9        /*No Constraints*/
     10}/*}}}*/
     11void MeltingAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
     12
     13        /*if 2d: Error*/
     14        if(iomodel->domaintype==Domain2DhorizontalEnum) _error_("2d meshes not supported yet");
     15
     16        //create penalties for nodes: no node can have a temperature over the melting point
     17        iomodel->FetchData(1,MeshVertexonbaseEnum);
     18        CreateSingleNodeToElementConnectivity(iomodel);
     19
     20        for(int i=0;i<iomodel->numberofvertices;i++){
     21                if(iomodel->my_vertices[i]){
     22                        if (reCast<int>(iomodel->Data(MeshVertexonbaseEnum)[i])){
     23                                loads->AddObject(new Pengrid(iomodel->loadcounter+i+1,i,iomodel,MeltingAnalysisEnum));
     24                        }
     25                }
     26        }
     27        iomodel->DeleteData(1,MeshVertexonbaseEnum);
     28
     29}/*}}}*/
     30void MeltingAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
     31
     32        if(iomodel->domaintype==Domain3DEnum) iomodel->FetchData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum);
     33        ::CreateNodes(nodes,iomodel,MeltingAnalysisEnum,P1Enum);
     34        iomodel->DeleteData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum);
     35}/*}}}*/
    836int  MeltingAnalysis::DofsPerNode(int** doflist,int domaintype,int approximation){/*{{{*/
    937        return 1;
    10 }/*}}}*/
    11 void MeltingAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
    1238}/*}}}*/
    1339void MeltingAnalysis::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/
     
    3965        iomodel->FetchDataToInput(elements,PressureEnum);
    4066}/*}}}*/
    41 void MeltingAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
    42 
    43         if(iomodel->domaintype==Domain3DEnum) iomodel->FetchData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum);
    44         ::CreateNodes(nodes,iomodel,MeltingAnalysisEnum,P1Enum);
    45         iomodel->DeleteData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum);
    46 }/*}}}*/
    47 void MeltingAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
    48         /*No Constraints*/
    49 }/*}}}*/
    50 void MeltingAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
    51 
    52         /*if 2d: Error*/
    53         if(iomodel->domaintype==Domain2DhorizontalEnum) _error_("2d meshes not supported yet");
    54 
    55         //create penalties for nodes: no node can have a temperature over the melting point
    56         iomodel->FetchData(1,MeshVertexonbaseEnum);
    57         CreateSingleNodeToElementConnectivity(iomodel);
    58 
    59         for(int i=0;i<iomodel->numberofvertices;i++){
    60                 if(iomodel->my_vertices[i]){
    61                         if (reCast<int>(iomodel->Data(MeshVertexonbaseEnum)[i])){
    62                                 loads->AddObject(new Pengrid(iomodel->loadcounter+i+1,i,iomodel,MeltingAnalysisEnum));
    63                         }
    64                 }
    65         }
    66         iomodel->DeleteData(1,MeshVertexonbaseEnum);
    67 
     67void MeltingAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
    6868}/*}}}*/
    6969
     
    126126        return NULL;
    127127}/*}}}*/
    128 void MeltingAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
     128void           MeltingAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
    129129           _error_("not implemented yet");
    130130}/*}}}*/
    131 void MeltingAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
     131void           MeltingAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
    132132        _error_("Not implemented yet");
    133133}/*}}}*/
    134 void MeltingAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
     134void           MeltingAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
    135135        element->InputUpdateFromSolutionOneDof(solution,BasalforcingsGroundediceMeltingRateEnum);
    136136}/*}}}*/
    137 void MeltingAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
     137void           MeltingAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
    138138        /*Default, do nothing*/
    139139        return;
  • issm/trunk-jpl/src/c/analyses/MeltingAnalysis.h

    r18057 r18930  
    1313        public:
    1414                /*Model processing*/
    15                 int  DofsPerNode(int** doflist,int domaintype,int approximation);
    16                 void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);
    17                 void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);
    18                 void CreateNodes(Nodes* nodes,IoModel* iomodel);
    1915                void CreateConstraints(Constraints* constraints,IoModel* iomodel);
    2016                void CreateLoads(Loads* loads, IoModel* iomodel);
     17                void CreateNodes(Nodes* nodes,IoModel* iomodel);
     18                int  DofsPerNode(int** doflist,int domaintype,int approximation);
     19                void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);
     20                void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);
    2121
    2222                /*Finite element Analysis*/
     
    2626                ElementMatrix* CreateKMatrix(Element* element);
    2727                ElementVector* CreatePVector(Element* element);
    28                 void GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);
    29                 void GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);
    30                 void InputUpdateFromSolution(IssmDouble* solution,Element* element);
    31                 void UpdateConstraints(FemModel* femmodel);
     28                void           GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);
     29                void           GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);
     30                void           InputUpdateFromSolution(IssmDouble* solution,Element* element);
     31                void           UpdateConstraints(FemModel* femmodel);
    3232};
    3333#endif
  • issm/trunk-jpl/src/c/analyses/MeshdeformationAnalysis.cpp

    r18057 r18930  
    66
    77/*Model processing*/
    8 int  MeshdeformationAnalysis::DofsPerNode(int** doflist,int domaintype,int approximation){/*{{{*/
    9         _error_("not implemented");
    10 }/*}}}*/
    11 void MeshdeformationAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
     8void MeshdeformationAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
    129           _error_("not implemented yet");
    1310}/*}}}*/
    14 void MeshdeformationAnalysis::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/
     11void MeshdeformationAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
    1512           _error_("not implemented yet");
    1613}/*}}}*/
     
    1815           _error_("not implemented yet");
    1916}/*}}}*/
    20 void MeshdeformationAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
     17int  MeshdeformationAnalysis::DofsPerNode(int** doflist,int domaintype,int approximation){/*{{{*/
     18        _error_("not implemented");
     19}/*}}}*/
     20void MeshdeformationAnalysis::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/
    2121           _error_("not implemented yet");
    2222}/*}}}*/
    23 void MeshdeformationAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
     23void MeshdeformationAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
    2424           _error_("not implemented yet");
    2525}/*}}}*/
     
    4242_error_("not implemented yet");
    4343}/*}}}*/
    44 void MeshdeformationAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
     44void           MeshdeformationAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
    4545           _error_("not implemented yet");
    4646}/*}}}*/
    47 void MeshdeformationAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
     47void           MeshdeformationAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
    4848        _error_("Not implemented yet");
    4949}/*}}}*/
    50 void MeshdeformationAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
     50void           MeshdeformationAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
    5151        _error_("not implemented yet");
    5252}/*}}}*/
    53 void MeshdeformationAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
     53void           MeshdeformationAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
    5454        /*Default, do nothing*/
    5555        return;
  • issm/trunk-jpl/src/c/analyses/MeshdeformationAnalysis.h

    r18057 r18930  
    1313        public:
    1414                /*Model processing*/
    15                 int  DofsPerNode(int** doflist,int domaintype,int approximation);
    16                 void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);
    17                 void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);
    18                 void CreateNodes(Nodes* nodes,IoModel* iomodel);
    1915                void CreateConstraints(Constraints* constraints,IoModel* iomodel);
    2016                void CreateLoads(Loads* loads, IoModel* iomodel);
     17                void CreateNodes(Nodes* nodes,IoModel* iomodel);
     18                int  DofsPerNode(int** doflist,int domaintype,int approximation);
     19                void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);
     20                void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);
    2121
    2222                /*Finite element Analysis*/
     
    2626                ElementMatrix* CreateKMatrix(Element* element);
    2727                ElementVector* CreatePVector(Element* element);
    28                 void GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);
    29                 void GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);
    30                 void InputUpdateFromSolution(IssmDouble* solution,Element* element);
    31                 void UpdateConstraints(FemModel* femmodel);
     28                void           GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);
     29                void           GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);
     30                void           InputUpdateFromSolution(IssmDouble* solution,Element* element);
     31                void           UpdateConstraints(FemModel* femmodel);
    3232};
    3333#endif
  • issm/trunk-jpl/src/c/analyses/SeaiceAnalysis.cpp

    r18624 r18930  
    66
    77/*Model processing*/
     8void SeaiceAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
     9
     10        const int finiteelement = P1Enum;
     11        IoModelToConstraintsx(constraints,iomodel,SeaiceSpcvxEnum,SeaiceAnalysisEnum,finiteelement,0);
     12        IoModelToConstraintsx(constraints,iomodel,SeaiceSpcvyEnum,SeaiceAnalysisEnum,finiteelement,1);
     13}/*}}}*/
     14void SeaiceAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
     15        return;
     16}/*}}}*/
     17void SeaiceAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
     18
     19        ::CreateNodes(nodes,iomodel,SeaiceAnalysisEnum,P1Enum);
     20
     21}/*}}}*/
    822int  SeaiceAnalysis::DofsPerNode(int** doflist,int domaintype,int approximation){/*{{{*/
    923        return 2;
    10 }/*}}}*/
    11 void SeaiceAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
    12         parameters->AddObject(iomodel->CopyConstantObject(SeaiceMinConcentrationEnum));
    13         parameters->AddObject(iomodel->CopyConstantObject(SeaiceMinThicknessEnum));
    14         parameters->AddObject(iomodel->CopyConstantObject(SeaiceMaxThicknessEnum));
    1524}/*}}}*/
    1625void SeaiceAnalysis::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/
     
    4958        iomodel->FetchDataToInput(elements,MeshYEnum);
    5059}/*}}}*/
    51 void SeaiceAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
    52 
    53         ::CreateNodes(nodes,iomodel,SeaiceAnalysisEnum,P1Enum);
    54 
    55 }/*}}}*/
    56 void SeaiceAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
    57 
    58         const int finiteelement = P1Enum;
    59         IoModelToConstraintsx(constraints,iomodel,SeaiceSpcvxEnum,SeaiceAnalysisEnum,finiteelement,0);
    60         IoModelToConstraintsx(constraints,iomodel,SeaiceSpcvyEnum,SeaiceAnalysisEnum,finiteelement,1);
    61 }/*}}}*/
    62 void SeaiceAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
    63         return;
     60void SeaiceAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
     61        parameters->AddObject(iomodel->CopyConstantObject(SeaiceMinConcentrationEnum));
     62        parameters->AddObject(iomodel->CopyConstantObject(SeaiceMinThicknessEnum));
     63        parameters->AddObject(iomodel->CopyConstantObject(SeaiceMaxThicknessEnum));
    6464}/*}}}*/
    6565
     
    312312        return pe;
    313313}/*}}}*/
    314 void SeaiceAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
     314void           SeaiceAnalysis::CreateCTensor(IssmDouble* C,Element* element,Gauss* gauss){/*{{{*/
     315
     316        /*Intermediaries*/
     317        IssmDouble D[3][3];
     318        IssmDouble damage,concentration;
     319
     320        /*Get Material parameters*/
     321        IssmDouble poisson          = element->GetMaterialParameter(MaterialsPoissonEnum);
     322        IssmDouble young_modulus    = element->GetMaterialParameter(MaterialsYoungModulusEnum);
     323        IssmDouble ridging_exponent = element->GetMaterialParameter(MaterialsRidgingExponentEnum);
     324
     325        /*Get damage input at this location*/
     326        Input* damage_input        = element->GetInput(DamageEnum);              _assert_(damage_input);
     327        Input* concentration_input = element->GetInput(SeaiceConcentrationEnum); _assert_(concentration_input);
     328        damage_input->GetInputValue(&damage,gauss);
     329        concentration_input->GetInputValue(&concentration,gauss);
     330
     331        /*Build D tensor once for all*/
     332        D[0][0] = 1.;      D[0][1] = poisson; D[0][2] = 0.;
     333        D[1][0] = poisson; D[1][1] = 1.;      D[1][2] = 0.;
     334        D[2][0] = 0.;      D[2][1] = 0;       D[2][2] = (1.-poisson)/2.;
     335        for(int i=0;i<3;i++){
     336                for(int j=0;j<3;j++){
     337                        D[i][j] = D[i][j]/(1-poisson*poisson);
     338                }
     339        }
     340
     341        /*Get f(A), E*/
     342        IssmDouble f = exp(ridging_exponent*(1.-concentration));
     343        IssmDouble E = young_modulus*(1.-damage)*f;
     344
     345        /*Let's build C = E*D */
     346        for(int i=0;i<3;i++){
     347                for(int j=0;j<3;j++){
     348                        C[i*3+j] = E*D[i][j];
     349                }
     350        }
     351}/*}}}*/
     352void           SeaiceAnalysis::GetB(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
     353        /*Compute B  matrix. B=[B1 B2 B3] where Bi is of size 3*NDOF2.
     354         * For node i, Bi can be expressed in the actual coordinate system
     355         * by:
     356         *       Bi=[ dN/dx           0    ]
     357         *          [   0           dN/dy  ]     
     358         *          [ 1/2*dN/dy  1/2*dN/dx ]     
     359         * where N is the basis function for node i.
     360         *
     361         * We assume B has been allocated already           */
     362
     363        /*Fetch number of nodes for this finite element*/
     364        int numnodes = element->GetNumberOfNodes();
     365
     366        /*Get nodal functions derivatives*/
     367        IssmDouble* dbasis=xNew<IssmDouble>(2*numnodes);
     368        element->NodalFunctionsDerivatives(dbasis,xyz_list,gauss);
     369
     370        /*Build B: */
     371        for(int i=0;i<numnodes;i++){
     372                B[2*numnodes*0+2*i+0] = dbasis[0*numnodes+i];
     373                B[2*numnodes*0+2*i+1] = 0.;
     374                B[2*numnodes*1+2*i+0] = 0.;
     375                B[2*numnodes*1+2*i+1] = dbasis[1*numnodes+i];
     376                //B[2*numnodes*2+2*i+0] = .5*dbasis[1*numnodes+i];
     377                //B[2*numnodes*2+2*i+1] = .5*dbasis[0*numnodes+i];
     378                B[2*numnodes*2+2*i+0] = dbasis[1*numnodes+i];
     379                B[2*numnodes*2+2*i+1] = dbasis[0*numnodes+i];
     380        }
     381
     382        /*Clean-up*/
     383        xDelete<IssmDouble>(dbasis);
     384}/*}}}*/
     385void           SeaiceAnalysis::GetM(IssmDouble* M,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
     386        /*Compute M  matrix. M=[M1 M2 M3] where Mi is of size 3*NDOF2.
     387         * For node i, Mi can be expressed in the actual coordinate system
     388         * by:
     389         *       Mi=[ N  N ]
     390         * where N is the basis function for node i.
     391         *
     392         * We assume M has been allocated already           */
     393
     394        /*Fetch number of nodes for this finite element*/
     395        int numnodes = element->GetNumberOfNodes();
     396
     397        /*Get nodal functions derivatives*/
     398        IssmDouble* basis=xNew<IssmDouble>(numnodes);
     399        element->NodalFunctions(basis,gauss);
     400
     401        /*Build M: */
     402        for(int i=0;i<numnodes;i++){
     403                M[2*i+0] = basis[i];
     404                M[2*i+1] = basis[i];
     405        }
     406
     407        /*Clean-up*/
     408        xDelete<IssmDouble>(basis);
     409}/*}}}*/
     410void           SeaiceAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
    315411           _error_("not implemented yet");
    316412}/*}}}*/
    317 void SeaiceAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
     413void           SeaiceAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
    318414        _error_("Not implemented yet");
    319415}/*}}}*/
    320 void SeaiceAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
     416void           SeaiceAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
    321417
    322418        /*Intermediaries*/
     
    360456        xDelete<int>(doflist);
    361457}/*}}}*/
    362 void SeaiceAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
     458void           SeaiceAnalysis::PostProcess(FemModel* femmodel){/*{{{*/
     459
     460        /*Intermediaties*/
     461        IssmDouble *xyz_list = NULL;
     462        IssmDouble *xyz_list_old = NULL;
     463        IssmDouble *xyz_list_new = NULL;
     464        IssmDouble  dt,meshx,meshy,vx,vy,eps_xx,eps_yy,eps_zz,area_old,area_new;
     465        IssmDouble  time_relaxation_stress,time_relaxation_damage,damage,concentration,thickness;
     466        IssmDouble  sigma_dot_xx,sigma_dot_yy,sigma_dot_xy;
     467        IssmDouble  sigma_pred_xx,sigma_pred_yy,sigma_pred_xy;
     468        IssmDouble  sigma_xx,sigma_yy,sigma_xy;
     469        IssmDouble  min_c,min_h,max_h;
     470        IssmDouble  epsilon[3]; /*eps_xx,eps_yy,eps_xy*/
     471        IssmDouble  C[3][3];
     472
     473        /*Fetch the parameters once for all*/
     474        femmodel->parameters->FindParam(&dt,TimesteppingTimeStepEnum);
     475        femmodel->parameters->FindParam(&min_c,SeaiceMinConcentrationEnum);
     476        femmodel->parameters->FindParam(&min_h,SeaiceMinThicknessEnum);
     477        femmodel->parameters->FindParam(&max_h,SeaiceMaxThicknessEnum);
     478
     479        /*Loop over the elements of this partition and update accordingly*/
     480        for(int i=0;i<femmodel->elements->Size();i++){
     481                Element* element=xDynamicCast<Element*>(femmodel->elements->GetObjectByOffset(i));
     482
     483                /*Get some inputs needed for the update*/
     484                element->GetVerticesCoordinates(&xyz_list);
     485                time_relaxation_stress = element->GetMaterialParameter(MaterialsTimeRelaxationStressEnum);
     486                time_relaxation_damage = element->GetMaterialParameter(MaterialsTimeRelaxationDamageEnum);
     487                Input* meshx_input = element->GetInput(MeshXEnum); _assert_(meshx_input);
     488                Input* meshy_input = element->GetInput(MeshYEnum); _assert_(meshy_input);
     489                Input* vx_input    = element->GetInput(VxEnum);    _assert_(vx_input);
     490                Input* vy_input    = element->GetInput(VyEnum);    _assert_(vy_input);
     491
     492                /*Preallocate future inputs*/
     493                int numvertices=element->GetNumberOfVertices();
     494                IssmDouble* meshx_new_list = xNew<IssmDouble>(numvertices);
     495                IssmDouble* meshy_new_list = xNew<IssmDouble>(numvertices);
     496                xyz_list_old = xNew<IssmDouble>(numvertices*3);
     497                xyz_list_new = xNew<IssmDouble>(numvertices*3);
     498
     499                /*1. update vertex positions (using a Gauss object for convenience)*/
     500                Gauss* gauss=element->NewGauss();
     501                for (int iv=0;iv<numvertices;iv++){
     502                        gauss->GaussVertex(iv);
     503
     504                        meshx_input->GetInputValue(&meshx,gauss);
     505                        meshy_input->GetInputValue(&meshy,gauss);
     506                        vx_input->GetInputValue(&vx,gauss);
     507                        vy_input->GetInputValue(&vy,gauss);
     508
     509                        meshx_new_list[iv] = meshx + vx*dt;
     510                        meshy_new_list[iv] = meshy + vy*dt;
     511
     512                        xyz_list_old[iv*3+0] = meshx;
     513                        xyz_list_old[iv*3+1] = meshy;
     514                        xyz_list_old[iv*3+2] = 0.;
     515
     516                        xyz_list_new[iv*3+0] = meshx_new_list[iv];
     517                        xyz_list_new[iv*3+1] = meshy_new_list[iv];
     518                        xyz_list_new[iv*3+2] = 0.;
     519                }
     520                element->AddInput(MeshXEnum,meshx_new_list,P1Enum);
     521                element->AddInput(MeshYEnum,meshy_new_list,P1Enum);
     522
     523                /*Now we are going to use a point in the center of the element, because we are P0 for the stress*/
     524                gauss->GaussNode(P0Enum,0);
     525
     526                /*Calculate sigma_dot*/
     527                sigma_dot_xx=sigma_dot_yy=sigma_dot_xy=0.;
     528                this->CreateCTensor(&C[0][0],element,gauss);
     529                element->StrainRateSSA(&epsilon[0],xyz_list,gauss,vx_input,vy_input);
     530                for(int j=0;j<3;j++){
     531                        sigma_dot_xx += C[0][j]*epsilon[0];
     532                        sigma_dot_yy += C[1][j]*epsilon[1];
     533                        sigma_dot_xy += C[2][j]*epsilon[2];
     534                }
     535
     536                /*Get predicted stress state*/
     537                Input* sigma_xx_input = element->GetInput(StressTensorPredictorxxEnum); _assert_(sigma_xx_input);
     538                Input* sigma_yy_input = element->GetInput(StressTensorPredictoryyEnum); _assert_(sigma_yy_input);
     539                Input* sigma_xy_input = element->GetInput(StressTensorPredictorxyEnum); _assert_(sigma_xy_input);
     540                sigma_xx_input->GetInputAverage(&sigma_xx);
     541                sigma_yy_input->GetInputAverage(&sigma_yy);
     542                sigma_xy_input->GetInputAverage(&sigma_xy);
     543
     544                /*Calculate new stress and push to element*/
     545                sigma_xx = sigma_xx + dt*(sigma_dot_xx - sigma_xx/time_relaxation_stress);
     546                sigma_yy = sigma_yy + dt*(sigma_dot_yy - sigma_yy/time_relaxation_stress);
     547                sigma_xy = sigma_xy + dt*(sigma_dot_xy - sigma_xy/time_relaxation_stress);
     548                element->AddInput(StressTensorxxEnum,&sigma_xx,P0Enum);
     549                element->AddInput(StressTensoryyEnum,&sigma_yy,P0Enum);
     550                element->AddInput(StressTensorxyEnum,&sigma_xy,P0Enum);
     551
     552                /*Update Damage According*/
     553                Input* damage_input = element->GetInput(DamageEnum); _assert_(damage_input);
     554                damage_input->GetInputAverage(&damage);
     555                damage = damage*(1.-dt/time_relaxation_damage);
     556                element->AddInput(DamageEnum,&damage,P0Enum);
     557
     558                /*Prepare new predictor*/
     559                this->CreateCTensor(&C[0][0],element,gauss); /*C is updated now that there is a new damage in inputs*/
     560                for(int j=0;j<3;j++){
     561                        sigma_pred_xx += C[0][j]*epsilon[0];
     562                        sigma_pred_yy += C[1][j]*epsilon[1];
     563                        sigma_pred_xy += C[2][j]*epsilon[2];
     564                }
     565                element->AddInput(StressTensorPredictorxxEnum,&sigma_pred_xx,P0Enum);
     566                element->AddInput(StressTensorPredictoryyEnum,&sigma_pred_yy,P0Enum);
     567                element->AddInput(StressTensorPredictorxyEnum,&sigma_pred_xy,P0Enum);
     568
     569                /*Calculate Old and new area (FIXME: for now we assume trianlges...)*/
     570                element->JacobianDeterminant(&area_old,xyz_list_old,gauss);
     571                element->JacobianDeterminant(&area_new,xyz_list_new,gauss);
     572                area_old = area_old/SQRT3;
     573                area_new = area_new/SQRT3;
     574
     575                /*Update ice thickness and concentration using element distortion*/
     576                Input* thickness_input     = element->GetInput(SeaiceThicknessEnum);     _assert_(thickness_input);
     577                Input* concentration_input = element->GetInput(SeaiceConcentrationEnum); _assert_(concentration_input);
     578                thickness_input->GetInputAverage(&thickness);
     579                concentration_input->GetInputAverage(&concentration);
     580                IssmDouble ice_area   = concentration*area_old;
     581                IssmDouble ice_volume = thickness*area_old;
     582                if(concentration>min_c){
     583                        concentration = ice_area  /area_new;
     584                        thickness     = ice_volume/area_new;
     585
     586                        /* lower bounds */
     587                        concentration = ((concentration>min_c)?(concentration):(min_c));
     588                        thickness     = ((thickness    >min_h)?(thickness    ):(min_h));
     589
     590                        /* upper bounds (only for the concentration) */
     591                        concentration    = ((concentration<1.   )?(concentration):(1));
     592                        thickness        = ((thickness    <max_h)?(thickness    ):(max_h));
     593                }
     594                element->AddInput(SeaiceConcentrationEnum,&concentration,P0Enum);
     595                element->AddInput(SeaiceThicknessEnum,&thickness,P0Enum);
     596
     597                /*Clean up*/
     598                xDelete<IssmDouble>(meshx_new_list);
     599                xDelete<IssmDouble>(meshy_new_list);
     600                xDelete<IssmDouble>(xyz_list);
     601                xDelete<IssmDouble>(xyz_list_old);
     602                xDelete<IssmDouble>(xyz_list_new);
     603        }
     604
     605}/*}}}*/
     606void           SeaiceAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
    363607
    364608        /*Intermediaries*/
     
    409653        if(VerboseSolution()) _printf0_("   Number of active nodes: "<< sum_counter <<"\n");
    410654}/*}}}*/
    411 
    412 /*Intermediary functions*/
    413 void SeaiceAnalysis::CreateCTensor(IssmDouble* C,Element* element,Gauss* gauss){/*{{{*/
    414 
    415         /*Intermediaries*/
    416         IssmDouble D[3][3];
    417         IssmDouble damage,concentration;
    418 
    419         /*Get Material parameters*/
    420         IssmDouble poisson          = element->GetMaterialParameter(MaterialsPoissonEnum);
    421         IssmDouble young_modulus    = element->GetMaterialParameter(MaterialsYoungModulusEnum);
    422         IssmDouble ridging_exponent = element->GetMaterialParameter(MaterialsRidgingExponentEnum);
    423 
    424         /*Get damage input at this location*/
    425         Input* damage_input        = element->GetInput(DamageEnum);              _assert_(damage_input);
    426         Input* concentration_input = element->GetInput(SeaiceConcentrationEnum); _assert_(concentration_input);
    427         damage_input->GetInputValue(&damage,gauss);
    428         concentration_input->GetInputValue(&concentration,gauss);
    429 
    430         /*Build D tensor once for all*/
    431         D[0][0] = 1.;      D[0][1] = poisson; D[0][2] = 0.;
    432         D[1][0] = poisson; D[1][1] = 1.;      D[1][2] = 0.;
    433         D[2][0] = 0.;      D[2][1] = 0;       D[2][2] = (1.-poisson)/2.;
    434         for(int i=0;i<3;i++){
    435                 for(int j=0;j<3;j++){
    436                         D[i][j] = D[i][j]/(1-poisson*poisson);
    437                 }
    438         }
    439 
    440         /*Get f(A), E*/
    441         IssmDouble f = exp(ridging_exponent*(1.-concentration));
    442         IssmDouble E = young_modulus*(1.-damage)*f;
    443 
    444         /*Let's build C = E*D */
    445         for(int i=0;i<3;i++){
    446                 for(int j=0;j<3;j++){
    447                         C[i*3+j] = E*D[i][j];
    448                 }
    449         }
    450 }/*}}}*/
    451 void SeaiceAnalysis::GetB(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
    452         /*Compute B  matrix. B=[B1 B2 B3] where Bi is of size 3*NDOF2.
    453          * For node i, Bi can be expressed in the actual coordinate system
    454          * by:
    455          *       Bi=[ dN/dx           0    ]
    456          *          [   0           dN/dy  ]     
    457          *          [ 1/2*dN/dy  1/2*dN/dx ]     
    458          * where N is the basis function for node i.
    459          *
    460          * We assume B has been allocated already           */
    461 
    462         /*Fetch number of nodes for this finite element*/
    463         int numnodes = element->GetNumberOfNodes();
    464 
    465         /*Get nodal functions derivatives*/
    466         IssmDouble* dbasis=xNew<IssmDouble>(2*numnodes);
    467         element->NodalFunctionsDerivatives(dbasis,xyz_list,gauss);
    468 
    469         /*Build B: */
    470         for(int i=0;i<numnodes;i++){
    471                 B[2*numnodes*0+2*i+0] = dbasis[0*numnodes+i];
    472                 B[2*numnodes*0+2*i+1] = 0.;
    473                 B[2*numnodes*1+2*i+0] = 0.;
    474                 B[2*numnodes*1+2*i+1] = dbasis[1*numnodes+i];
    475                 //B[2*numnodes*2+2*i+0] = .5*dbasis[1*numnodes+i];
    476                 //B[2*numnodes*2+2*i+1] = .5*dbasis[0*numnodes+i];
    477                 B[2*numnodes*2+2*i+0] = dbasis[1*numnodes+i];
    478                 B[2*numnodes*2+2*i+1] = dbasis[0*numnodes+i];
    479         }
    480 
    481         /*Clean-up*/
    482         xDelete<IssmDouble>(dbasis);
    483 }/*}}}*/
    484 void SeaiceAnalysis::GetM(IssmDouble* M,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
    485         /*Compute M  matrix. M=[M1 M2 M3] where Mi is of size 3*NDOF2.
    486          * For node i, Mi can be expressed in the actual coordinate system
    487          * by:
    488          *       Mi=[ N  N ]
    489          * where N is the basis function for node i.
    490          *
    491          * We assume M has been allocated already           */
    492 
    493         /*Fetch number of nodes for this finite element*/
    494         int numnodes = element->GetNumberOfNodes();
    495 
    496         /*Get nodal functions derivatives*/
    497         IssmDouble* basis=xNew<IssmDouble>(numnodes);
    498         element->NodalFunctions(basis,gauss);
    499 
    500         /*Build M: */
    501         for(int i=0;i<numnodes;i++){
    502                 M[2*i+0] = basis[i];
    503                 M[2*i+1] = basis[i];
    504         }
    505 
    506         /*Clean-up*/
    507         xDelete<IssmDouble>(basis);
    508 }/*}}}*/
    509 void SeaiceAnalysis::UpdateDamageAndStress(FemModel* femmodel){/*{{{*/
     655void           SeaiceAnalysis::UpdateDamageAndStress(FemModel* femmodel){/*{{{*/
    510656        /* The damage variable is updated as a function of the actual elastic deformation
    511657         * In both cases, a Coulombic enveloppe is used, define by the cohesion C, tan(phi) and tract_coef.
     
    622768        }
    623769}/*}}}*/
    624 void SeaiceAnalysis::PostProcess(FemModel* femmodel){/*{{{*/
    625 
    626         /*Intermediaties*/
    627         IssmDouble *xyz_list = NULL;
    628         IssmDouble *xyz_list_old = NULL;
    629         IssmDouble *xyz_list_new = NULL;
    630         IssmDouble  dt,meshx,meshy,vx,vy,eps_xx,eps_yy,eps_zz,area_old,area_new;
    631         IssmDouble  time_relaxation_stress,time_relaxation_damage,damage,concentration,thickness;
    632         IssmDouble  sigma_dot_xx,sigma_dot_yy,sigma_dot_xy;
    633         IssmDouble  sigma_pred_xx,sigma_pred_yy,sigma_pred_xy;
    634         IssmDouble  sigma_xx,sigma_yy,sigma_xy;
    635         IssmDouble  min_c,min_h,max_h;
    636         IssmDouble  epsilon[3]; /*eps_xx,eps_yy,eps_xy*/
    637         IssmDouble  C[3][3];
    638 
    639         /*Fetch the parameters once for all*/
    640         femmodel->parameters->FindParam(&dt,TimesteppingTimeStepEnum);
    641         femmodel->parameters->FindParam(&min_c,SeaiceMinConcentrationEnum);
    642         femmodel->parameters->FindParam(&min_h,SeaiceMinThicknessEnum);
    643         femmodel->parameters->FindParam(&max_h,SeaiceMaxThicknessEnum);
    644 
    645         /*Loop over the elements of this partition and update accordingly*/
    646         for(int i=0;i<femmodel->elements->Size();i++){
    647                 Element* element=xDynamicCast<Element*>(femmodel->elements->GetObjectByOffset(i));
    648 
    649                 /*Get some inputs needed for the update*/
    650                 element->GetVerticesCoordinates(&xyz_list);
    651                 time_relaxation_stress = element->GetMaterialParameter(MaterialsTimeRelaxationStressEnum);
    652                 time_relaxation_damage = element->GetMaterialParameter(MaterialsTimeRelaxationDamageEnum);
    653                 Input* meshx_input = element->GetInput(MeshXEnum); _assert_(meshx_input);
    654                 Input* meshy_input = element->GetInput(MeshYEnum); _assert_(meshy_input);
    655                 Input* vx_input    = element->GetInput(VxEnum);    _assert_(vx_input);
    656                 Input* vy_input    = element->GetInput(VyEnum);    _assert_(vy_input);
    657 
    658                 /*Preallocate future inputs*/
    659                 int numvertices=element->GetNumberOfVertices();
    660                 IssmDouble* meshx_new_list = xNew<IssmDouble>(numvertices);
    661                 IssmDouble* meshy_new_list = xNew<IssmDouble>(numvertices);
    662                 xyz_list_old = xNew<IssmDouble>(numvertices*3);
    663                 xyz_list_new = xNew<IssmDouble>(numvertices*3);
    664 
    665                 /*1. update vertex positions (using a Gauss object for convenience)*/
    666                 Gauss* gauss=element->NewGauss();
    667                 for (int iv=0;iv<numvertices;iv++){
    668                         gauss->GaussVertex(iv);
    669 
    670                         meshx_input->GetInputValue(&meshx,gauss);
    671                         meshy_input->GetInputValue(&meshy,gauss);
    672                         vx_input->GetInputValue(&vx,gauss);
    673                         vy_input->GetInputValue(&vy,gauss);
    674 
    675                         meshx_new_list[iv] = meshx + vx*dt;
    676                         meshy_new_list[iv] = meshy + vy*dt;
    677 
    678                         xyz_list_old[iv*3+0] = meshx;
    679                         xyz_list_old[iv*3+1] = meshy;
    680                         xyz_list_old[iv*3+2] = 0.;
    681 
    682                         xyz_list_new[iv*3+0] = meshx_new_list[iv];
    683                         xyz_list_new[iv*3+1] = meshy_new_list[iv];
    684                         xyz_list_new[iv*3+2] = 0.;
    685                 }
    686                 element->AddInput(MeshXEnum,meshx_new_list,P1Enum);
    687                 element->AddInput(MeshYEnum,meshy_new_list,P1Enum);
    688 
    689                 /*Now we are going to use a point in the center of the element, because we are P0 for the stress*/
    690                 gauss->GaussNode(P0Enum,0);
    691 
    692                 /*Calculate sigma_dot*/
    693                 sigma_dot_xx=sigma_dot_yy=sigma_dot_xy=0.;
    694                 this->CreateCTensor(&C[0][0],element,gauss);
    695                 element->StrainRateSSA(&epsilon[0],xyz_list,gauss,vx_input,vy_input);
    696                 for(int j=0;j<3;j++){
    697                         sigma_dot_xx += C[0][j]*epsilon[0];
    698                         sigma_dot_yy += C[1][j]*epsilon[1];
    699                         sigma_dot_xy += C[2][j]*epsilon[2];
    700                 }
    701 
    702                 /*Get predicted stress state*/
    703                 Input* sigma_xx_input = element->GetInput(StressTensorPredictorxxEnum); _assert_(sigma_xx_input);
    704                 Input* sigma_yy_input = element->GetInput(StressTensorPredictoryyEnum); _assert_(sigma_yy_input);
    705                 Input* sigma_xy_input = element->GetInput(StressTensorPredictorxyEnum); _assert_(sigma_xy_input);
    706                 sigma_xx_input->GetInputAverage(&sigma_xx);
    707                 sigma_yy_input->GetInputAverage(&sigma_yy);
    708                 sigma_xy_input->GetInputAverage(&sigma_xy);
    709 
    710                 /*Calculate new stress and push to element*/
    711                 sigma_xx = sigma_xx + dt*(sigma_dot_xx - sigma_xx/time_relaxation_stress);
    712                 sigma_yy = sigma_yy + dt*(sigma_dot_yy - sigma_yy/time_relaxation_stress);
    713                 sigma_xy = sigma_xy + dt*(sigma_dot_xy - sigma_xy/time_relaxation_stress);
    714                 element->AddInput(StressTensorxxEnum,&sigma_xx,P0Enum);
    715                 element->AddInput(StressTensoryyEnum,&sigma_yy,P0Enum);
    716                 element->AddInput(StressTensorxyEnum,&sigma_xy,P0Enum);
    717 
    718                 /*Update Damage According*/
    719                 Input* damage_input = element->GetInput(DamageEnum); _assert_(damage_input);
    720                 damage_input->GetInputAverage(&damage);
    721                 damage = damage*(1.-dt/time_relaxation_damage);
    722                 element->AddInput(DamageEnum,&damage,P0Enum);
    723 
    724                 /*Prepare new predictor*/
    725                 this->CreateCTensor(&C[0][0],element,gauss); /*C is updated now that there is a new damage in inputs*/
    726                 for(int j=0;j<3;j++){
    727                         sigma_pred_xx += C[0][j]*epsilon[0];
    728                         sigma_pred_yy += C[1][j]*epsilon[1];
    729                         sigma_pred_xy += C[2][j]*epsilon[2];
    730                 }
    731                 element->AddInput(StressTensorPredictorxxEnum,&sigma_pred_xx,P0Enum);
    732                 element->AddInput(StressTensorPredictoryyEnum,&sigma_pred_yy,P0Enum);
    733                 element->AddInput(StressTensorPredictorxyEnum,&sigma_pred_xy,P0Enum);
    734 
    735                 /*Calculate Old and new area (FIXME: for now we assume trianlges...)*/
    736                 element->JacobianDeterminant(&area_old,xyz_list_old,gauss);
    737                 element->JacobianDeterminant(&area_new,xyz_list_new,gauss);
    738                 area_old = area_old/SQRT3;
    739                 area_new = area_new/SQRT3;
    740 
    741                 /*Update ice thickness and concentration using element distortion*/
    742                 Input* thickness_input     = element->GetInput(SeaiceThicknessEnum);     _assert_(thickness_input);
    743                 Input* concentration_input = element->GetInput(SeaiceConcentrationEnum); _assert_(concentration_input);
    744                 thickness_input->GetInputAverage(&thickness);
    745                 concentration_input->GetInputAverage(&concentration);
    746                 IssmDouble ice_area   = concentration*area_old;
    747                 IssmDouble ice_volume = thickness*area_old;
    748                 if(concentration>min_c){
    749                         concentration = ice_area  /area_new;
    750                         thickness     = ice_volume/area_new;
    751 
    752                         /* lower bounds */
    753                         concentration = ((concentration>min_c)?(concentration):(min_c));
    754                         thickness     = ((thickness    >min_h)?(thickness    ):(min_h));
    755 
    756                         /* upper bounds (only for the concentration) */
    757                         concentration    = ((concentration<1.   )?(concentration):(1));
    758                         thickness        = ((thickness    <max_h)?(thickness    ):(max_h));
    759                 }
    760                 element->AddInput(SeaiceConcentrationEnum,&concentration,P0Enum);
    761                 element->AddInput(SeaiceThicknessEnum,&thickness,P0Enum);
    762 
    763                 /*Clean up*/
    764                 xDelete<IssmDouble>(meshx_new_list);
    765                 xDelete<IssmDouble>(meshy_new_list);
    766                 xDelete<IssmDouble>(xyz_list);
    767                 xDelete<IssmDouble>(xyz_list_old);
    768                 xDelete<IssmDouble>(xyz_list_new);
    769         }
    770 
    771 }/*}}}*/
  • issm/trunk-jpl/src/c/analyses/SeaiceAnalysis.h

    r18505 r18930  
    1313        public:
    1414                /*Model processing*/
    15                 int  DofsPerNode(int** doflist,int domaintype,int approximation);
    16                 void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);
    17                 void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);
    18                 void CreateNodes(Nodes* nodes,IoModel* iomodel);
    1915                void CreateConstraints(Constraints* constraints,IoModel* iomodel);
    2016                void CreateLoads(Loads* loads, IoModel* iomodel);
     17                void CreateNodes(Nodes* nodes,IoModel* iomodel);
     18                int  DofsPerNode(int** doflist,int domaintype,int approximation);
     19                void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);
     20                void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);
    2121
    2222                /*Finite element Analysis*/
    2323                void           Core(FemModel* femmodel);
     24                void           CreateCTensor(IssmDouble* C,Element* element,Gauss* gauss);
    2425                ElementVector* CreateDVector(Element* element);
    2526                ElementMatrix* CreateJacobianMatrix(Element* element);
    2627                ElementMatrix* CreateKMatrix(Element* element);
    2728                ElementVector* CreatePVector(Element* element);
    28                 void GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);
    29                 void GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);
    30                 void InputUpdateFromSolution(IssmDouble* solution,Element* element);
    31                 void UpdateConstraints(FemModel* femmodel);
    32 
    33                 /*Sea ice specifics*/
    34                 void UpdateDamageAndStress(FemModel* femmodel);
    35                 void CreateCTensor(IssmDouble* C,Element* element,Gauss* gauss);
    36                 void GetB(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss);
    37                 void GetM(IssmDouble* M,Element* element,IssmDouble* xyz_list,Gauss* gauss);
    38                 void PostProcess(FemModel* femmodel);
     29                void           GetB(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss);
     30                void           GetM(IssmDouble* M,Element* element,IssmDouble* xyz_list,Gauss* gauss);
     31                void           GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);
     32                void           GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);
     33                void           InputUpdateFromSolution(IssmDouble* solution,Element* element);
     34                void           PostProcess(FemModel* femmodel);
     35                void           UpdateConstraints(FemModel* femmodel);
     36                void           UpdateDamageAndStress(FemModel* femmodel);
    3937};
    4038#endif
  • issm/trunk-jpl/src/c/analyses/SmoothAnalysis.cpp

    r18604 r18930  
    66
    77/*Model processing*/
     8void SmoothAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
     9}/*}}}*/
     10void SmoothAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
     11}/*}}}*/
     12void SmoothAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
     13
     14        ::CreateNodes(nodes,iomodel,SmoothAnalysisEnum,P1Enum);
     15
     16}/*}}}*/
    817int  SmoothAnalysis::DofsPerNode(int** doflist,int domaintype,int approximation){/*{{{*/
    918        return 1;
    10 }/*}}}*/
    11 void SmoothAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
    1219}/*}}}*/
    1320void SmoothAnalysis::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/
     
    2330        }
    2431}/*}}}*/
    25 void SmoothAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
    26 
    27         ::CreateNodes(nodes,iomodel,SmoothAnalysisEnum,P1Enum);
    28 
    29 }/*}}}*/
    30 void SmoothAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
    31 }/*}}}*/
    32 void SmoothAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
     32void SmoothAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
    3333}/*}}}*/
    3434
     
    205205        return pe;
    206206}/*}}}*/
    207 void SmoothAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
     207void           SmoothAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
    208208           _error_("not implemented yet");
    209209}/*}}}*/
    210 void SmoothAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
     210void           SmoothAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
    211211        _error_("Not implemented yet");
    212212}/*}}}*/
    213 void SmoothAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
     213void           SmoothAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
    214214        int inputenum,domaintype,elementtype;
    215215
     
    223223        }
    224224}/*}}}*/
    225 void SmoothAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
     225void           SmoothAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
    226226        /*Default, do nothing*/
    227227        return;
  • issm/trunk-jpl/src/c/analyses/SmoothAnalysis.h

    r18593 r18930  
    1313        public:
    1414                /*Model processing*/
    15                 int  DofsPerNode(int** doflist,int domaintype,int approximation);
    16                 void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);
    17                 void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);
    18                 void CreateNodes(Nodes* nodes,IoModel* iomodel);
    1915                void CreateConstraints(Constraints* constraints,IoModel* iomodel);
    2016                void CreateLoads(Loads* loads, IoModel* iomodel);
     17                void CreateNodes(Nodes* nodes,IoModel* iomodel);
     18                int  DofsPerNode(int** doflist,int domaintype,int approximation);
     19                void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);
     20                void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);
    2121
    2222                /*Finite element Analysis*/
     
    2626                ElementMatrix* CreateKMatrix(Element* element);
    2727                ElementVector* CreatePVector(Element* element);
    28                 void GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);
    29                 void GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);
    30                 void InputUpdateFromSolution(IssmDouble* solution,Element* element);
    31                 void UpdateConstraints(FemModel* femmodel);
     28                void           GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);
     29                void           GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);
     30                void           InputUpdateFromSolution(IssmDouble* solution,Element* element);
     31                void           UpdateConstraints(FemModel* femmodel);
    3232};
    3333#endif
  • issm/trunk-jpl/src/c/analyses/StressbalanceSIAAnalysis.cpp

    r18068 r18930  
    77
    88/*Model processing*/
    9 int  StressbalanceSIAAnalysis::DofsPerNode(int** doflist,int domaintype,int approximation){/*{{{*/
    10         return 2;
    11 }/*}}}*/
    12 void StressbalanceSIAAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
    13 
    14         /*No specific parameters*/
    15 
    16 }/*}}}*/
    17 void StressbalanceSIAAnalysis::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/
    18 
    19         /*Fetch data needed: */
    20         bool   isSIA;
    21         bool   islevelset;
    22         iomodel->Constant(&isSIA,FlowequationIsSIAEnum);
    23         iomodel->Constant(&islevelset,TransientIslevelsetEnum);
    24 
    25         /*Now, is the flag SIA on? otherwise, do nothing: */
    26         if (!isSIA)return;
    27 
    28         iomodel->FetchData(1,FlowequationElementEquationEnum);
    29 
    30         /*Update elements: */
    31         int counter=0;
    32         for(int i=0;i<iomodel->numberofelements;i++){
    33                 if(iomodel->my_elements[i]){
    34                         Element* element=(Element*)elements->GetObjectByOffset(counter);
    35                         element->Update(i,iomodel,analysis_counter,analysis_type,P1Enum);
    36                         counter++;
    37                 }
    38         }
    39 
    40         iomodel->FetchDataToInput(elements,ThicknessEnum);
    41         iomodel->FetchDataToInput(elements,FrictionCoefficientEnum);
    42         iomodel->FetchDataToInput(elements,MaskGroundediceLevelsetEnum);
    43         if(islevelset){
    44                 iomodel->FetchDataToInput(elements,IceMaskNodeActivationEnum);
    45                 if(iomodel->domaintype!=Domain2DhorizontalEnum)
    46                         iomodel->FetchDataToInput(elements,MeshVertexonbaseEnum); // required for updating active nodes
    47         }
    48 
    49         /*Free data: */
    50         iomodel->DeleteData(1,FlowequationElementEquationEnum);
    51 }/*}}}*/
    52 void StressbalanceSIAAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
    53 
    54         /*Intermediaries*/
    55         bool  isSIA;
    56         Node* node = NULL;
    57 
    58         /*Fetch parameters: */
    59         iomodel->Constant(&isSIA,FlowequationIsSIAEnum);
    60 
    61         /*Now, is the flag isSIA on? otherwise, do nothing: */
    62         if(!isSIA) return;
    63 
    64         /*First create nodes*/
    65         int    lid=0;
    66         iomodel->FetchData(4,FlowequationBorderSSAEnum,FlowequationBorderFSEnum,FlowequationVertexEquationEnum,StressbalanceReferentialEnum);
    67         if(iomodel->domaintype!=Domain2DhorizontalEnum){
    68                 iomodel->FetchData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum);
    69         }
    70 
    71         for(int i=0;i<iomodel->numberofvertices;i++){
    72                 if(iomodel->my_vertices[i]){
    73 
    74                         /*Create new node if is in this processor's partition*/
    75                         node = new Node(iomodel->nodecounter+i+1,i,lid++,i,iomodel,StressbalanceSIAAnalysisEnum,reCast<int>(iomodel->Data(FlowequationVertexEquationEnum)[i]));
    76 
    77                         /*Deactivate node if not SIA*/
    78                         if(reCast<int>(iomodel->Data(FlowequationVertexEquationEnum)[i])!=SIAApproximationEnum){
    79                                 node->Deactivate();
    80                         }
    81 
    82                         /*Add to Nodes dataset*/
    83                         nodes->AddObject(node);
    84                 }
    85         }
    86 
    87         iomodel->DeleteData(6,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum,FlowequationBorderSSAEnum,FlowequationBorderFSEnum,
    88                                 FlowequationVertexEquationEnum,StressbalanceReferentialEnum);
    89 
    90 }/*}}}*/
    919void StressbalanceSIAAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
    9210
     
    14260
    14361        /*No loads*/
     62
     63}/*}}}*/
     64void StressbalanceSIAAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
     65
     66        /*Intermediaries*/
     67        bool  isSIA;
     68        Node* node = NULL;
     69
     70        /*Fetch parameters: */
     71        iomodel->Constant(&isSIA,FlowequationIsSIAEnum);
     72
     73        /*Now, is the flag isSIA on? otherwise, do nothing: */
     74        if(!isSIA) return;
     75
     76        /*First create nodes*/
     77        int    lid=0;
     78        iomodel->FetchData(4,FlowequationBorderSSAEnum,FlowequationBorderFSEnum,FlowequationVertexEquationEnum,StressbalanceReferentialEnum);
     79        if(iomodel->domaintype!=Domain2DhorizontalEnum){
     80                iomodel->FetchData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum);
     81        }
     82
     83        for(int i=0;i<iomodel->numberofvertices;i++){
     84                if(iomodel->my_vertices[i]){
     85
     86                        /*Create new node if is in this processor's partition*/
     87                        node = new Node(iomodel->nodecounter+i+1,i,lid++,i,iomodel,StressbalanceSIAAnalysisEnum,reCast<int>(iomodel->Data(FlowequationVertexEquationEnum)[i]));
     88
     89                        /*Deactivate node if not SIA*/
     90                        if(reCast<int>(iomodel->Data(FlowequationVertexEquationEnum)[i])!=SIAApproximationEnum){
     91                                node->Deactivate();
     92                        }
     93
     94                        /*Add to Nodes dataset*/
     95                        nodes->AddObject(node);
     96                }
     97        }
     98
     99        iomodel->DeleteData(6,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum,FlowequationBorderSSAEnum,FlowequationBorderFSEnum,
     100                                FlowequationVertexEquationEnum,StressbalanceReferentialEnum);
     101
     102}/*}}}*/
     103int  StressbalanceSIAAnalysis::DofsPerNode(int** doflist,int domaintype,int approximation){/*{{{*/
     104        return 2;
     105}/*}}}*/
     106void StressbalanceSIAAnalysis::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/
     107
     108        /*Fetch data needed: */
     109        bool   isSIA;
     110        bool   islevelset;
     111        iomodel->Constant(&isSIA,FlowequationIsSIAEnum);
     112        iomodel->Constant(&islevelset,TransientIslevelsetEnum);
     113
     114        /*Now, is the flag SIA on? otherwise, do nothing: */
     115        if (!isSIA)return;
     116
     117        iomodel->FetchData(1,FlowequationElementEquationEnum);
     118
     119        /*Update elements: */
     120        int counter=0;
     121        for(int i=0;i<iomodel->numberofelements;i++){
     122                if(iomodel->my_elements[i]){
     123                        Element* element=(Element*)elements->GetObjectByOffset(counter);
     124                        element->Update(i,iomodel,analysis_counter,analysis_type,P1Enum);
     125                        counter++;
     126                }
     127        }
     128
     129        iomodel->FetchDataToInput(elements,ThicknessEnum);
     130        iomodel->FetchDataToInput(elements,FrictionCoefficientEnum);
     131        iomodel->FetchDataToInput(elements,MaskGroundediceLevelsetEnum);
     132        if(islevelset){
     133                iomodel->FetchDataToInput(elements,IceMaskNodeActivationEnum);
     134                if(iomodel->domaintype!=Domain2DhorizontalEnum)
     135                        iomodel->FetchDataToInput(elements,MeshVertexonbaseEnum); // required for updating active nodes
     136        }
     137
     138        /*Free data: */
     139        iomodel->DeleteData(1,FlowequationElementEquationEnum);
     140}/*}}}*/
     141void StressbalanceSIAAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
     142
     143        /*No specific parameters*/
    144144
    145145}/*}}}*/
     
    461461
    462462}/*}}}*/
    463 void StressbalanceSIAAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
     463void           StressbalanceSIAAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
    464464
    465465        IssmDouble vx,vy;
     
    494494        xDelete<IssmDouble>(values);
    495495}/*}}}*/
    496 void StressbalanceSIAAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
     496void           StressbalanceSIAAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
    497497        _error_("Not implemented yet");
    498498}/*}}}*/
    499 void StressbalanceSIAAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
     499void           StressbalanceSIAAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
    500500
    501501        int         i,domaintype;
     
    581581        xDelete<int>(doflist);
    582582}/*}}}*/
    583 void StressbalanceSIAAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
     583void           StressbalanceSIAAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
    584584
    585585        bool islevelset;
  • issm/trunk-jpl/src/c/analyses/StressbalanceSIAAnalysis.h

    r18057 r18930  
    1313        public:
    1414                /*Model processing*/
    15                 int  DofsPerNode(int** doflist,int domaintype,int approximation);
    16                 void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);
    17                 void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);
    18                 void CreateNodes(Nodes* nodes,IoModel* iomodel);
    1915                void CreateConstraints(Constraints* constraints,IoModel* iomodel);
    2016                void CreateLoads(Loads* loads, IoModel* iomodel);
     17                void CreateNodes(Nodes* nodes,IoModel* iomodel);
     18                int  DofsPerNode(int** doflist,int domaintype,int approximation);
     19                void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);
     20                void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);
    2121
    2222                /*Finite element Analysis*/
     
    3030                ElementVector* CreatePVector2D(Element* element);
    3131                ElementVector* CreatePVector3D(Element* element);
    32                 void GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);
    33                 void GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);
    34                 void InputUpdateFromSolution(IssmDouble* solution,Element* element);
    35                 void UpdateConstraints(FemModel* femmodel);
     32                void           GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);
     33                void           GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);
     34                void           InputUpdateFromSolution(IssmDouble* solution,Element* element);
     35                void           UpdateConstraints(FemModel* femmodel);
    3636};
    3737#endif
  • issm/trunk-jpl/src/c/analyses/StressbalanceVerticalAnalysis.cpp

    r18074 r18930  
    77
    88/*Model processing*/
    9 int  StressbalanceVerticalAnalysis::DofsPerNode(int** doflist,int domaintype,int approximation){/*{{{*/
    10         return 1;
    11 }/*}}}*/
    12 void StressbalanceVerticalAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
    13 
    14         /*No specific parameters*/
    15 
    16 }/*}}}*/
    17 void StressbalanceVerticalAnalysis::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/
    18 
    19         /*return if not 3d mesh*/
    20         if(iomodel->domaintype!=Domain3DEnum) return;
    21 
    22         /*Update elements: */
    23         int counter=0;
    24         for(int i=0;i<iomodel->numberofelements;i++){
    25                 if(iomodel->my_elements[i]){
    26                         Element* element=(Element*)elements->GetObjectByOffset(counter);
    27                         element->Update(i,iomodel,analysis_counter,analysis_type,P1Enum);
    28                         counter++;
    29                 }
    30         }
    31 
    32         iomodel->FetchDataToInput(elements,ThicknessEnum);
    33         iomodel->FetchDataToInput(elements,SurfaceEnum);
    34         iomodel->FetchDataToInput(elements,BaseEnum);
    35         iomodel->FetchDataToInput(elements,MaskIceLevelsetEnum);
    36         if(iomodel->domaintype!=Domain2DhorizontalEnum){
    37                 iomodel->FetchDataToInput(elements,MeshVertexonbaseEnum);
    38                 iomodel->FetchDataToInput(elements,MeshVertexonsurfaceEnum);
    39         }
    40         iomodel->FetchDataToInput(elements,BasalforcingsGroundediceMeltingRateEnum);
    41         iomodel->FetchDataToInput(elements,BasalforcingsFloatingiceMeltingRateEnum);
    42         iomodel->FetchDataToInput(elements,VxEnum,0.);
    43         iomodel->FetchDataToInput(elements,VyEnum,0.);
    44 }/*}}}*/
    45 void StressbalanceVerticalAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
    46 
    47         /*return if not 3d mesh*/
    48         if(iomodel->domaintype!=Domain3DEnum) return;
    49 
    50         iomodel->FetchData(3,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum,FlowequationVertexEquationEnum);
    51         ::CreateNodes(nodes,iomodel,StressbalanceVerticalAnalysisEnum,P1Enum);
    52         iomodel->DeleteData(3,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum,FlowequationVertexEquationEnum);
    53 }/*}}}*/
    549void StressbalanceVerticalAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
    5510
     
    9853
    9954}/*}}}*/
     55void StressbalanceVerticalAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
     56
     57        /*return if not 3d mesh*/
     58        if(iomodel->domaintype!=Domain3DEnum) return;
     59
     60        iomodel->FetchData(3,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum,FlowequationVertexEquationEnum);
     61        ::CreateNodes(nodes,iomodel,StressbalanceVerticalAnalysisEnum,P1Enum);
     62        iomodel->DeleteData(3,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum,FlowequationVertexEquationEnum);
     63}/*}}}*/
     64int  StressbalanceVerticalAnalysis::DofsPerNode(int** doflist,int domaintype,int approximation){/*{{{*/
     65        return 1;
     66}/*}}}*/
     67void StressbalanceVerticalAnalysis::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/
     68
     69        /*return if not 3d mesh*/
     70        if(iomodel->domaintype!=Domain3DEnum) return;
     71
     72        /*Update elements: */
     73        int counter=0;
     74        for(int i=0;i<iomodel->numberofelements;i++){
     75                if(iomodel->my_elements[i]){
     76                        Element* element=(Element*)elements->GetObjectByOffset(counter);
     77                        element->Update(i,iomodel,analysis_counter,analysis_type,P1Enum);
     78                        counter++;
     79                }
     80        }
     81
     82        iomodel->FetchDataToInput(elements,ThicknessEnum);
     83        iomodel->FetchDataToInput(elements,SurfaceEnum);
     84        iomodel->FetchDataToInput(elements,BaseEnum);
     85        iomodel->FetchDataToInput(elements,MaskIceLevelsetEnum);
     86        if(iomodel->domaintype!=Domain2DhorizontalEnum){
     87                iomodel->FetchDataToInput(elements,MeshVertexonbaseEnum);
     88                iomodel->FetchDataToInput(elements,MeshVertexonsurfaceEnum);
     89        }
     90        iomodel->FetchDataToInput(elements,BasalforcingsGroundediceMeltingRateEnum);
     91        iomodel->FetchDataToInput(elements,BasalforcingsFloatingiceMeltingRateEnum);
     92        iomodel->FetchDataToInput(elements,VxEnum,0.);
     93        iomodel->FetchDataToInput(elements,VyEnum,0.);
     94}/*}}}*/
     95void StressbalanceVerticalAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
     96
     97        /*No specific parameters*/
     98
     99}/*}}}*/
    100100
    101101/*Finite Element Analysis*/
     
    125125        return Ke;
    126126
     127}/*}}}*/
     128ElementMatrix* StressbalanceVerticalAnalysis::CreateKMatrixSurface(Element* element){/*{{{*/
     129
     130
     131        if(!element->IsOnSurface()) return NULL;
     132
     133        /*Intermediaries*/
     134        IssmDouble  D,Jdet,normal[3];
     135        IssmDouble *xyz_list = NULL;
     136
     137        /*Fetch number of nodes and dof for this finite element*/
     138        int numnodes = element->GetNumberOfNodes();
     139
     140        /*Initialize Element matrix and vectors*/
     141        ElementMatrix* Ke    = element->NewElementMatrix(NoneApproximationEnum);
     142        IssmDouble*    basis = xNew<IssmDouble>(numnodes);
     143
     144        /*Retrieve all inputs and parameters*/
     145        element->GetVerticesCoordinatesTop(&xyz_list);
     146
     147        /* Start  looping on the number of gaussian points: */
     148        Gauss* gauss = element->NewGaussTop(2);
     149        element->NormalTop(&normal[0],xyz_list);
     150        for(int ig=gauss->begin();ig<gauss->end();ig++){
     151                gauss->GaussPoint(ig);
     152
     153                element->JacobianDeterminantTop(&Jdet,xyz_list,gauss);
     154                element->NodalFunctions(basis,gauss);
     155                D = -gauss->weight*Jdet*normal[2];
     156
     157                TripleMultiply( basis,1,numnodes,1,
     158                                        &D,1,1,0,
     159                                        basis,1,numnodes,0,
     160                                        &Ke->values[0],1);
     161        }
     162
     163        /*Clean up and return*/
     164        delete gauss;
     165        xDelete<IssmDouble>(xyz_list);
     166        xDelete<IssmDouble>(basis);
     167        return Ke;
    127168}/*}}}*/
    128169ElementMatrix* StressbalanceVerticalAnalysis::CreateKMatrixVolume(Element* element){/*{{{*/
     
    167208
    168209}/*}}}*/
    169 ElementMatrix* StressbalanceVerticalAnalysis::CreateKMatrixSurface(Element* element){/*{{{*/
    170 
    171 
    172         if(!element->IsOnSurface()) return NULL;
    173 
    174         /*Intermediaries*/
    175         IssmDouble  D,Jdet,normal[3];
    176         IssmDouble *xyz_list = NULL;
    177 
    178         /*Fetch number of nodes and dof for this finite element*/
    179         int numnodes = element->GetNumberOfNodes();
    180 
    181         /*Initialize Element matrix and vectors*/
    182         ElementMatrix* Ke    = element->NewElementMatrix(NoneApproximationEnum);
    183         IssmDouble*    basis = xNew<IssmDouble>(numnodes);
    184 
    185         /*Retrieve all inputs and parameters*/
    186         element->GetVerticesCoordinatesTop(&xyz_list);
    187 
    188         /* Start  looping on the number of gaussian points: */
    189         Gauss* gauss = element->NewGaussTop(2);
    190         element->NormalTop(&normal[0],xyz_list);
    191         for(int ig=gauss->begin();ig<gauss->end();ig++){
    192                 gauss->GaussPoint(ig);
    193 
    194                 element->JacobianDeterminantTop(&Jdet,xyz_list,gauss);
    195                 element->NodalFunctions(basis,gauss);
    196                 D = -gauss->weight*Jdet*normal[2];
    197 
    198                 TripleMultiply( basis,1,numnodes,1,
    199                                         &D,1,1,0,
    200                                         basis,1,numnodes,0,
    201                                         &Ke->values[0],1);
    202         }
    203 
    204         /*Clean up and return*/
    205         delete gauss;
    206         xDelete<IssmDouble>(xyz_list);
    207         xDelete<IssmDouble>(basis);
    208         return Ke;
    209 }/*}}}*/
    210210ElementVector* StressbalanceVerticalAnalysis::CreatePVector(Element* element){/*{{{*/
    211211
     
    218218        delete pe1;
    219219        delete pe2;
    220         return pe;
    221 }/*}}}*/
    222 ElementVector* StressbalanceVerticalAnalysis::CreatePVectorVolume(Element* element){/*{{{*/
    223 
    224         /*Intermediaries*/
    225         int         approximation;
    226         IssmDouble  Jdet,dudx,dvdy,dwdz;
    227         IssmDouble  du[3],dv[3],dw[3];
    228         IssmDouble* xyz_list = NULL;
    229 
    230         /*Fetch number of nodes for this finite element*/
    231         int numnodes = element->GetNumberOfNodes();
    232 
    233         /*Initialize Element vector and basis functions*/
    234         ElementVector* pe    = element->NewElementVector();
    235         IssmDouble*    basis = xNew<IssmDouble>(numnodes);
    236 
    237         /*Retrieve all inputs and parameters*/
    238         element->GetVerticesCoordinates(&xyz_list);
    239         element->GetInputValue(&approximation,ApproximationEnum);
    240         Input* vx_input=element->GetInput(VxEnum); _assert_(vx_input);
    241         Input* vy_input=element->GetInput(VyEnum); _assert_(vy_input);
    242         Input* vzFS_input=NULL;
    243         if(approximation==HOFSApproximationEnum || approximation==SSAFSApproximationEnum){
    244                 vzFS_input=element->GetInput(VzFSEnum); _assert_(vzFS_input);
    245         }
    246 
    247         /* Start  looping on the number of gaussian points: */
    248         Gauss* gauss=element->NewGauss(2);
    249         for(int ig=gauss->begin();ig<gauss->end();ig++){
    250                 gauss->GaussPoint(ig);
    251 
    252                 element->JacobianDeterminant(&Jdet,xyz_list,gauss);
    253                 element->NodalFunctions(basis,gauss);
    254 
    255                 vx_input->GetInputDerivativeValue(&du[0],xyz_list,gauss);
    256                 vy_input->GetInputDerivativeValue(&dv[0],xyz_list,gauss);
    257                 if(approximation==HOFSApproximationEnum || approximation==SSAFSApproximationEnum){
    258                         vzFS_input->GetInputDerivativeValue(&dw[0],xyz_list,gauss);
    259                         dwdz=dw[2];
    260                 }
    261                 else dwdz=0;
    262                 dudx=du[0];
    263                 dvdy=dv[1];
    264 
    265                 for(int i=0;i<numnodes;i++) pe->values[i] += (dudx+dvdy+dwdz)*Jdet*gauss->weight*basis[i];
    266         }
    267 
    268         /*Clean up and return*/
    269         delete gauss;
    270         xDelete<IssmDouble>(basis);
    271         xDelete<IssmDouble>(xyz_list);
    272220        return pe;
    273221}/*}}}*/
     
    338286        return pe;
    339287}/*}}}*/
    340 void StressbalanceVerticalAnalysis::GetB(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
     288ElementVector* StressbalanceVerticalAnalysis::CreatePVectorVolume(Element* element){/*{{{*/
     289
     290        /*Intermediaries*/
     291        int         approximation;
     292        IssmDouble  Jdet,dudx,dvdy,dwdz;
     293        IssmDouble  du[3],dv[3],dw[3];
     294        IssmDouble* xyz_list = NULL;
     295
     296        /*Fetch number of nodes for this finite element*/
     297        int numnodes = element->GetNumberOfNodes();
     298
     299        /*Initialize Element vector and basis functions*/
     300        ElementVector* pe    = element->NewElementVector();
     301        IssmDouble*    basis = xNew<IssmDouble>(numnodes);
     302
     303        /*Retrieve all inputs and parameters*/
     304        element->GetVerticesCoordinates(&xyz_list);
     305        element->GetInputValue(&approximation,ApproximationEnum);
     306        Input* vx_input=element->GetInput(VxEnum); _assert_(vx_input);
     307        Input* vy_input=element->GetInput(VyEnum); _assert_(vy_input);
     308        Input* vzFS_input=NULL;
     309        if(approximation==HOFSApproximationEnum || approximation==SSAFSApproximationEnum){
     310                vzFS_input=element->GetInput(VzFSEnum); _assert_(vzFS_input);
     311        }
     312
     313        /* Start  looping on the number of gaussian points: */
     314        Gauss* gauss=element->NewGauss(2);
     315        for(int ig=gauss->begin();ig<gauss->end();ig++){
     316                gauss->GaussPoint(ig);
     317
     318                element->JacobianDeterminant(&Jdet,xyz_list,gauss);
     319                element->NodalFunctions(basis,gauss);
     320
     321                vx_input->GetInputDerivativeValue(&du[0],xyz_list,gauss);
     322                vy_input->GetInputDerivativeValue(&dv[0],xyz_list,gauss);
     323                if(approximation==HOFSApproximationEnum || approximation==SSAFSApproximationEnum){
     324                        vzFS_input->GetInputDerivativeValue(&dw[0],xyz_list,gauss);
     325                        dwdz=dw[2];
     326                }
     327                else dwdz=0;
     328                dudx=du[0];
     329                dvdy=dv[1];
     330
     331                for(int i=0;i<numnodes;i++) pe->values[i] += (dudx+dvdy+dwdz)*Jdet*gauss->weight*basis[i];
     332        }
     333
     334        /*Clean up and return*/
     335        delete gauss;
     336        xDelete<IssmDouble>(basis);
     337        xDelete<IssmDouble>(xyz_list);
     338        return pe;
     339}/*}}}*/
     340void           StressbalanceVerticalAnalysis::GetB(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
    341341        /*      Compute B  matrix. B=[dh1/dz dh2/dz dh3/dz dh4/dz dh5/dz dh6/dz];
    342342                where hi is the interpolation function for node i.*/
     
    357357        xDelete<IssmDouble>(dbasis);
    358358}/*}}}*/
    359 void StressbalanceVerticalAnalysis::GetBprime(IssmDouble* Bprime,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
     359void           StressbalanceVerticalAnalysis::GetBprime(IssmDouble* Bprime,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
    360360
    361361        element->NodalFunctions(Bprime,gauss);
    362362
    363363}/*}}}*/
    364 void StressbalanceVerticalAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
     364void           StressbalanceVerticalAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
    365365        element->GetSolutionFromInputsOneDof(solution,VzEnum);
    366366}/*}}}*/
    367 void StressbalanceVerticalAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
     367void           StressbalanceVerticalAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
    368368        _error_("Not implemented yet");
    369369}/*}}}*/
    370 void StressbalanceVerticalAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
     370void           StressbalanceVerticalAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
    371371
    372372        int          numnodes = element->GetNumberOfNodes();
     
    481481        xDelete<int>(doflist);
    482482}/*}}}*/
    483 void StressbalanceVerticalAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
     483void           StressbalanceVerticalAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
    484484        /*Default, do nothing*/
    485485        return;
  • issm/trunk-jpl/src/c/analyses/StressbalanceVerticalAnalysis.h

    r18057 r18930  
    1313        public:
    1414                /*Model processing*/
    15                 int  DofsPerNode(int** doflist,int domaintype,int approximation);
    16                 void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);
    17                 void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);
    18                 void CreateNodes(Nodes* nodes,IoModel* iomodel);
    1915                void CreateConstraints(Constraints* constraints,IoModel* iomodel);
    2016                void CreateLoads(Loads* loads, IoModel* iomodel);
     17                void CreateNodes(Nodes* nodes,IoModel* iomodel);
     18                int  DofsPerNode(int** doflist,int domaintype,int approximation);
     19                void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);
     20                void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);
    2121
    2222                /*Finite element Analysis*/
     
    2525                ElementMatrix* CreateJacobianMatrix(Element* element);
    2626                ElementMatrix* CreateKMatrix(Element* element);
     27                ElementMatrix* CreateKMatrixSurface(Element* element);
    2728                ElementMatrix* CreateKMatrixVolume(Element* element);
    28                 ElementMatrix* CreateKMatrixSurface(Element* element);
    2929                ElementVector* CreatePVector(Element* element);
     30                ElementVector* CreatePVectorBase(Element* element);
    3031                ElementVector* CreatePVectorVolume(Element* element);
    31                 ElementVector* CreatePVectorBase(Element* element);
    32                 void GetB(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss);
    33                 void GetBprime(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss);
    34                 void GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);
    35                 void GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);
    36                 void InputUpdateFromSolution(IssmDouble* solution,Element* element);
    37                 void UpdateConstraints(FemModel* femmodel);
     32                void           GetB(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss);
     33                void           GetBprime(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss);
     34                void           GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);
     35                void           GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);
     36                void           InputUpdateFromSolution(IssmDouble* solution,Element* element);
     37                void           UpdateConstraints(FemModel* femmodel);
    3838};
    3939#endif
  • issm/trunk-jpl/src/c/analyses/ThermalAnalysis.cpp

    r18804 r18930  
    66
    77/*Model processing*/
     8void ThermalAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
     9
     10        /*Only 3d mesh supported*/
     11        int finiteelement = P1Enum;
     12        if(iomodel->domaintype==Domain3DEnum){
     13                IoModelToConstraintsx(constraints,iomodel,ThermalSpctemperatureEnum,ThermalAnalysisEnum,finiteelement);
     14        }
     15
     16}/*}}}*/
     17void ThermalAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
     18
     19        if(iomodel->domaintype==Domain2DhorizontalEnum) _error_("2d meshes not supported yet");
     20
     21        /*create penalties for nodes: no node can have a temperature over the melting point*/
     22        iomodel->FetchData(1,ThermalSpctemperatureEnum);
     23        CreateSingleNodeToElementConnectivity(iomodel);
     24
     25        for(int i=0;i<iomodel->numberofvertices;i++){
     26
     27                /*keep only this partition's nodes:*/
     28                if(iomodel->my_vertices[i]){
     29                        if (xIsNan<IssmDouble>(iomodel->Data(ThermalSpctemperatureEnum)[i])){ //No penalty applied on spc nodes!
     30                                loads->AddObject(new Pengrid(iomodel->loadcounter+i+1,i,iomodel,ThermalAnalysisEnum));
     31                        }
     32                }
     33        }
     34        iomodel->DeleteData(1,ThermalSpctemperatureEnum);
     35
     36}/*}}}*/
     37void ThermalAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
     38
     39        int finiteelement = P1Enum;
     40        if(iomodel->domaintype==Domain3DEnum) iomodel->FetchData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum);
     41        ::CreateNodes(nodes,iomodel,ThermalAnalysisEnum,finiteelement);
     42        iomodel->DeleteData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum);
     43}/*}}}*/
    844int  ThermalAnalysis::DofsPerNode(int** doflist,int domaintype,int approximation){/*{{{*/
    945        return 1;
    10 }/*}}}*/
    11 void ThermalAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
    12 
    13         int     numoutputs;
    14         char**  requestedoutputs = NULL;
    15 
    16         parameters->AddObject(iomodel->CopyConstantObject(ThermalMaxiterEnum));
    17         parameters->AddObject(iomodel->CopyConstantObject(ThermalStabilizationEnum));
    18         parameters->AddObject(iomodel->CopyConstantObject(ThermalPenaltyFactorEnum));
    19         parameters->AddObject(iomodel->CopyConstantObject(ThermalPenaltyThresholdEnum));
    20         parameters->AddObject(iomodel->CopyConstantObject(ThermalPenaltyLockEnum));
    21         parameters->AddObject(iomodel->CopyConstantObject(ThermalIsenthalpyEnum));
    22         parameters->AddObject(iomodel->CopyConstantObject(ThermalIsdynamicbasalspcEnum));
    23         parameters->AddObject(iomodel->CopyConstantObject(FrictionLawEnum));
    24 
    25         iomodel->FetchData(&requestedoutputs,&numoutputs,ThermalRequestedOutputsEnum);
    26         parameters->AddObject(new IntParam(ThermalNumRequestedOutputsEnum,numoutputs));
    27         if(numoutputs)parameters->AddObject(new StringArrayParam(ThermalRequestedOutputsEnum,requestedoutputs,numoutputs));
    28         iomodel->DeleteData(&requestedoutputs,numoutputs,ThermalRequestedOutputsEnum);
    29 
    30         /*Deal with friction parameters*/
    31         int frictionlaw;
    32         iomodel->Constant(&frictionlaw,FrictionLawEnum);
    33         if(frictionlaw==4 || frictionlaw==6) parameters->AddObject(iomodel->CopyConstantObject(FrictionGammaEnum));
    3446}/*}}}*/
    3547void ThermalAnalysis::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/
     
    122134        }
    123135}/*}}}*/
    124 void ThermalAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
    125 
    126         int finiteelement = P1Enum;
    127         if(iomodel->domaintype==Domain3DEnum) iomodel->FetchData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum);
    128         ::CreateNodes(nodes,iomodel,ThermalAnalysisEnum,finiteelement);
    129         iomodel->DeleteData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum);
    130 }/*}}}*/
    131 void ThermalAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
    132 
    133         /*Only 3d mesh supported*/
    134         int finiteelement = P1Enum;
    135         if(iomodel->domaintype==Domain3DEnum){
    136                 IoModelToConstraintsx(constraints,iomodel,ThermalSpctemperatureEnum,ThermalAnalysisEnum,finiteelement);
    137         }
    138 
    139 }/*}}}*/
    140 void ThermalAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
    141 
    142         if(iomodel->domaintype==Domain2DhorizontalEnum) _error_("2d meshes not supported yet");
    143 
    144         /*create penalties for nodes: no node can have a temperature over the melting point*/
    145         iomodel->FetchData(1,ThermalSpctemperatureEnum);
    146         CreateSingleNodeToElementConnectivity(iomodel);
    147 
    148         for(int i=0;i<iomodel->numberofvertices;i++){
    149 
    150                 /*keep only this partition's nodes:*/
    151                 if(iomodel->my_vertices[i]){
    152                         if (xIsNan<IssmDouble>(iomodel->Data(ThermalSpctemperatureEnum)[i])){ //No penalty applied on spc nodes!
    153                                 loads->AddObject(new Pengrid(iomodel->loadcounter+i+1,i,iomodel,ThermalAnalysisEnum));
    154                         }
    155                 }
    156         }
    157         iomodel->DeleteData(1,ThermalSpctemperatureEnum);
    158 
     136void ThermalAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
     137
     138        int     numoutputs;
     139        char**  requestedoutputs = NULL;
     140
     141        parameters->AddObject(iomodel->CopyConstantObject(ThermalMaxiterEnum));
     142        parameters->AddObject(iomodel->CopyConstantObject(ThermalStabilizationEnum));
     143        parameters->AddObject(iomodel->CopyConstantObject(ThermalPenaltyFactorEnum));
     144        parameters->AddObject(iomodel->CopyConstantObject(ThermalPenaltyThresholdEnum));
     145        parameters->AddObject(iomodel->CopyConstantObject(ThermalPenaltyLockEnum));
     146        parameters->AddObject(iomodel->CopyConstantObject(ThermalIsenthalpyEnum));
     147        parameters->AddObject(iomodel->CopyConstantObject(ThermalIsdynamicbasalspcEnum));
     148        parameters->AddObject(iomodel->CopyConstantObject(FrictionLawEnum));
     149
     150        iomodel->FetchData(&requestedoutputs,&numoutputs,ThermalRequestedOutputsEnum);
     151        parameters->AddObject(new IntParam(ThermalNumRequestedOutputsEnum,numoutputs));
     152        if(numoutputs)parameters->AddObject(new StringArrayParam(ThermalRequestedOutputsEnum,requestedoutputs,numoutputs));
     153        iomodel->DeleteData(&requestedoutputs,numoutputs,ThermalRequestedOutputsEnum);
     154
     155        /*Deal with friction parameters*/
     156        int frictionlaw;
     157        iomodel->Constant(&frictionlaw,FrictionLawEnum);
     158        if(frictionlaw==4 || frictionlaw==6) parameters->AddObject(iomodel->CopyConstantObject(FrictionGammaEnum));
    159159}/*}}}*/
    160160
     
    183183        delete Ke1;
    184184        delete Ke2;
     185        return Ke;
     186}/*}}}*/
     187ElementMatrix* ThermalAnalysis::CreateKMatrixShelf(Element* element){/*{{{*/
     188
     189        /* Check if ice in element */
     190        if(!element->IsIceInElement()) return NULL;
     191
     192        /*Initialize Element matrix and return if necessary*/
     193        if(!element->IsOnBase() || !element->IsFloating()) return NULL;
     194
     195        IssmDouble  dt,Jdet,D;
     196        IssmDouble *xyz_list_base = NULL;
     197
     198        /*Get basal element*/
     199        if(!element->IsOnBase() || !element->IsFloating()) return NULL;
     200
     201        /*Fetch number of nodes for this finite element*/
     202        int numnodes = element->GetNumberOfNodes();
     203
     204        /*Initialize vectors*/
     205        ElementMatrix* Ke    = element->NewElementMatrix();
     206        IssmDouble*    basis = xNew<IssmDouble>(numnodes);
     207
     208        /*Retrieve all inputs and parameters*/
     209        element->GetVerticesCoordinatesBase(&xyz_list_base);
     210        element->FindParam(&dt,TimesteppingTimeStepEnum);
     211        IssmDouble  gravity             = element->GetMaterialParameter(ConstantsGEnum);
     212        IssmDouble  rho_water           = element->GetMaterialParameter(MaterialsRhoSeawaterEnum);
     213        IssmDouble  rho_ice             = element->GetMaterialParameter(MaterialsRhoIceEnum);
     214        IssmDouble  heatcapacity        = element->GetMaterialParameter(MaterialsHeatcapacityEnum);
     215        IssmDouble  mixed_layer_capacity= element->GetMaterialParameter(MaterialsMixedLayerCapacityEnum);
     216        IssmDouble  thermal_exchange_vel= element->GetMaterialParameter(MaterialsThermalExchangeVelocityEnum);
     217
     218        /* Start  looping on the number of gaussian points: */
     219        Gauss* gauss=element->NewGaussBase(2);
     220        for(int ig=gauss->begin();ig<gauss->end();ig++){
     221                gauss->GaussPoint(ig);
     222
     223                element->JacobianDeterminantBase(&Jdet,xyz_list_base,gauss);
     224                element->NodalFunctions(basis,gauss);
     225
     226                D=gauss->weight*Jdet*rho_water*mixed_layer_capacity*thermal_exchange_vel/(heatcapacity*rho_ice);
     227                if(reCast<bool,IssmDouble>(dt)) D=dt*D;
     228                TripleMultiply(basis,numnodes,1,0,
     229                                        &D,1,1,0,
     230                                        basis,1,numnodes,0,
     231                                        &Ke->values[0],1);
     232
     233        }
     234
     235        /*Clean up and return*/
     236        delete gauss;
     237        xDelete<IssmDouble>(basis);
     238        xDelete<IssmDouble>(xyz_list_base);
    185239        return Ke;
    186240}/*}}}*/
     
    318372        return Ke;
    319373}/*}}}*/
    320 ElementMatrix* ThermalAnalysis::CreateKMatrixShelf(Element* element){/*{{{*/
    321 
     374ElementVector* ThermalAnalysis::CreatePVector(Element* element){/*{{{*/
     375       
    322376        /* Check if ice in element */
    323377        if(!element->IsIceInElement()) return NULL;
    324378
    325         /*Initialize Element matrix and return if necessary*/
    326         if(!element->IsOnBase() || !element->IsFloating()) return NULL;
    327 
    328         IssmDouble  dt,Jdet,D;
     379        /*compute all load vectors for this element*/
     380        ElementVector* pe1=CreatePVectorVolume(element);
     381        ElementVector* pe2=CreatePVectorSheet(element);
     382        ElementVector* pe3=CreatePVectorShelf(element);
     383        ElementVector* pe =new ElementVector(pe1,pe2,pe3);
     384
     385        /*clean-up and return*/
     386        delete pe1;
     387        delete pe2;
     388        delete pe3;
     389        return pe;
     390}/*}}}*/
     391ElementVector* ThermalAnalysis::CreatePVectorSheet(Element* element){/*{{{*/
     392
     393        /* Check if ice in element */
     394        if(!element->IsIceInElement()) return NULL;
     395
     396        /* Geothermal flux on ice sheet base and basal friction */
     397        if(!element->IsOnBase() || element->IsFloating()) return NULL;
     398
     399        IssmDouble  dt,Jdet,geothermalflux,vx,vy,vz;
     400        IssmDouble  alpha2,scalar,basalfriction,heatflux;
    329401        IssmDouble *xyz_list_base = NULL;
    330402
    331         /*Get basal element*/
    332         if(!element->IsOnBase() || !element->IsFloating()) return NULL;
    333 
    334403        /*Fetch number of nodes for this finite element*/
    335404        int numnodes = element->GetNumberOfNodes();
    336405
    337406        /*Initialize vectors*/
    338         ElementMatrix* Ke    = element->NewElementMatrix();
     407        ElementVector* pe    = element->NewElementVector();
    339408        IssmDouble*    basis = xNew<IssmDouble>(numnodes);
    340409
     
    342411        element->GetVerticesCoordinatesBase(&xyz_list_base);
    343412        element->FindParam(&dt,TimesteppingTimeStepEnum);
     413        Input* vx_input             = element->GetInput(VxEnum);                          _assert_(vx_input);
     414        Input* vy_input             = element->GetInput(VyEnum);                          _assert_(vy_input);
     415        Input* vz_input             = element->GetInput(VzEnum);                          _assert_(vz_input);
     416        Input* geothermalflux_input = element->GetInput(BasalforcingsGeothermalfluxEnum); _assert_(geothermalflux_input);
     417        IssmDouble  rho_ice             = element->GetMaterialParameter(MaterialsRhoIceEnum);
     418        IssmDouble  heatcapacity        = element->GetMaterialParameter(MaterialsHeatcapacityEnum);
     419
     420        /*Build friction element, needed later: */
     421        Friction* friction=new Friction(element,3);
     422
     423        /* Start  looping on the number of gaussian points: */
     424        Gauss* gauss   = element->NewGaussBase(2);
     425        for(int ig=gauss->begin();ig<gauss->end();ig++){
     426                gauss->GaussPoint(ig);
     427
     428                element->JacobianDeterminantBase(&Jdet,xyz_list_base,gauss);
     429                element->NodalFunctions(basis,gauss);
     430
     431                geothermalflux_input->GetInputValue(&geothermalflux,gauss);
     432                friction->GetAlpha2(&alpha2,gauss);
     433                vx_input->GetInputValue(&vx,gauss);
     434                vy_input->GetInputValue(&vy,gauss);
     435                vz_input->GetInputValue(&vz,gauss);
     436                vz = 0.;//FIXME
     437                basalfriction = alpha2*(vx*vx + vy*vy + vz*vz);
     438                heatflux      = (basalfriction+geothermalflux)/(rho_ice*heatcapacity);
     439
     440                scalar = gauss->weight*Jdet*heatflux;
     441                if(dt!=0.) scalar=dt*scalar;
     442
     443                for(int i=0;i<numnodes;i++) pe->values[i]+=scalar*basis[i];
     444        }
     445
     446        /*Clean up and return*/
     447        delete gauss;
     448        delete friction;
     449        xDelete<IssmDouble>(basis);
     450        xDelete<IssmDouble>(xyz_list_base);
     451        return pe;
     452}/*}}}*/
     453ElementVector* ThermalAnalysis::CreatePVectorShelf(Element* element){/*{{{*/
     454
     455        /* Check if ice in element */
     456        if(!element->IsIceInElement()) return NULL;
     457
     458        IssmDouble  t_pmp,dt,Jdet,scalar_ocean,pressure;
     459        IssmDouble *xyz_list_base = NULL;
     460
     461        /*Get basal element*/
     462        if(!element->IsOnBase() || !element->IsFloating()) return NULL;
     463
     464        /*Fetch number of nodes for this finite element*/
     465        int numnodes = element->GetNumberOfNodes();
     466
     467        /*Initialize vectors*/
     468        ElementVector* pe    = element->NewElementVector();
     469        IssmDouble*    basis = xNew<IssmDouble>(numnodes);
     470
     471        /*Retrieve all inputs and parameters*/
     472        element->GetVerticesCoordinatesBase(&xyz_list_base);
     473        element->FindParam(&dt,TimesteppingTimeStepEnum);
     474        Input*      pressure_input=element->GetInput(PressureEnum); _assert_(pressure_input);
    344475        IssmDouble  gravity             = element->GetMaterialParameter(ConstantsGEnum);
    345476        IssmDouble  rho_water           = element->GetMaterialParameter(MaterialsRhoSeawaterEnum);
     
    357488                element->NodalFunctions(basis,gauss);
    358489
    359                 D=gauss->weight*Jdet*rho_water*mixed_layer_capacity*thermal_exchange_vel/(heatcapacity*rho_ice);
    360                 if(reCast<bool,IssmDouble>(dt)) D=dt*D;
    361                 TripleMultiply(basis,numnodes,1,0,
    362                                         &D,1,1,0,
    363                                         basis,1,numnodes,0,
    364                                         &Ke->values[0],1);
    365 
     490                pressure_input->GetInputValue(&pressure,gauss);
     491                t_pmp=element->TMeltingPoint(pressure);
     492
     493                scalar_ocean=gauss->weight*Jdet*rho_water*mixed_layer_capacity*thermal_exchange_vel*(t_pmp)/(heatcapacity*rho_ice);
     494                if(reCast<bool,IssmDouble>(dt)) scalar_ocean=dt*scalar_ocean;
     495
     496                for(int i=0;i<numnodes;i++) pe->values[i]+=scalar_ocean*basis[i];
    366497        }
    367498
     
    370501        xDelete<IssmDouble>(basis);
    371502        xDelete<IssmDouble>(xyz_list_base);
    372         return Ke;
    373 }/*}}}*/
    374 ElementVector* ThermalAnalysis::CreatePVector(Element* element){/*{{{*/
    375        
    376         /* Check if ice in element */
    377         if(!element->IsIceInElement()) return NULL;
    378 
    379         /*compute all load vectors for this element*/
    380         ElementVector* pe1=CreatePVectorVolume(element);
    381         ElementVector* pe2=CreatePVectorSheet(element);
    382         ElementVector* pe3=CreatePVectorShelf(element);
    383         ElementVector* pe =new ElementVector(pe1,pe2,pe3);
    384 
    385         /*clean-up and return*/
    386         delete pe1;
    387         delete pe2;
    388         delete pe3;
    389503        return pe;
    390504}/*}}}*/
     
    471585
    472586}/*}}}*/
    473 ElementVector* ThermalAnalysis::CreatePVectorSheet(Element* element){/*{{{*/
    474 
    475         /* Check if ice in element */
    476         if(!element->IsIceInElement()) return NULL;
    477 
    478         /* Geothermal flux on ice sheet base and basal friction */
    479         if(!element->IsOnBase() || element->IsFloating()) return NULL;
    480 
    481         IssmDouble  dt,Jdet,geothermalflux,vx,vy,vz;
    482         IssmDouble  alpha2,scalar,basalfriction,heatflux;
    483         IssmDouble *xyz_list_base = NULL;
     587void           ThermalAnalysis::GetBAdvec(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
     588        /*Compute B  matrix. B=[B1 B2 B3 B4 B5 B6] where Bi is of size 5*NDOF1.
     589         * For node i, Bi' can be expressed in the actual coordinate system
     590         * by:
     591         *       Bi_advec =[ h ]
     592         *                 [ h ]
     593         *                 [ h ]
     594         * where h is the interpolation function for node i.
     595         *
     596         * We assume B has been allocated already, of size: 3x(NDOF1*NUMNODESP1)
     597         */
    484598
    485599        /*Fetch number of nodes for this finite element*/
    486600        int numnodes = element->GetNumberOfNodes();
    487601
    488         /*Initialize vectors*/
    489         ElementVector* pe    = element->NewElementVector();
    490         IssmDouble*    basis = xNew<IssmDouble>(numnodes);
    491 
    492         /*Retrieve all inputs and parameters*/
    493         element->GetVerticesCoordinatesBase(&xyz_list_base);
    494         element->FindParam(&dt,TimesteppingTimeStepEnum);
    495         Input* vx_input             = element->GetInput(VxEnum);                          _assert_(vx_input);
    496         Input* vy_input             = element->GetInput(VyEnum);                          _assert_(vy_input);
    497         Input* vz_input             = element->GetInput(VzEnum);                          _assert_(vz_input);
    498         Input* geothermalflux_input = element->GetInput(BasalforcingsGeothermalfluxEnum); _assert_(geothermalflux_input);
    499         IssmDouble  rho_ice             = element->GetMaterialParameter(MaterialsRhoIceEnum);
    500         IssmDouble  heatcapacity        = element->GetMaterialParameter(MaterialsHeatcapacityEnum);
    501 
    502         /*Build friction element, needed later: */
    503         Friction* friction=new Friction(element,3);
    504 
    505         /* Start  looping on the number of gaussian points: */
    506         Gauss* gauss   = element->NewGaussBase(2);
    507         for(int ig=gauss->begin();ig<gauss->end();ig++){
    508                 gauss->GaussPoint(ig);
    509 
    510                 element->JacobianDeterminantBase(&Jdet,xyz_list_base,gauss);
    511                 element->NodalFunctions(basis,gauss);
    512 
    513                 geothermalflux_input->GetInputValue(&geothermalflux,gauss);
    514                 friction->GetAlpha2(&alpha2,gauss);
    515                 vx_input->GetInputValue(&vx,gauss);
    516                 vy_input->GetInputValue(&vy,gauss);
    517                 vz_input->GetInputValue(&vz,gauss);
    518                 vz = 0.;//FIXME
    519                 basalfriction = alpha2*(vx*vx + vy*vy + vz*vz);
    520                 heatflux      = (basalfriction+geothermalflux)/(rho_ice*heatcapacity);
    521 
    522                 scalar = gauss->weight*Jdet*heatflux;
    523                 if(dt!=0.) scalar=dt*scalar;
    524 
    525                 for(int i=0;i<numnodes;i++) pe->values[i]+=scalar*basis[i];
    526         }
    527 
    528         /*Clean up and return*/
    529         delete gauss;
    530         delete friction;
     602        /*Get nodal functions*/
     603        IssmDouble* basis=xNew<IssmDouble>(numnodes);
     604        element->NodalFunctions(basis,gauss);
     605
     606        /*Build B: */
     607        for(int i=0;i<numnodes;i++){
     608                B[numnodes*0+i] = basis[i];
     609                B[numnodes*1+i] = basis[i];
     610                B[numnodes*2+i] = basis[i];
     611        }
     612
     613        /*Clean-up*/
    531614        xDelete<IssmDouble>(basis);
    532         xDelete<IssmDouble>(xyz_list_base);
    533         return pe;
    534 }/*}}}*/
    535 ElementVector* ThermalAnalysis::CreatePVectorShelf(Element* element){/*{{{*/
    536 
    537         /* Check if ice in element */
    538         if(!element->IsIceInElement()) return NULL;
    539 
    540         IssmDouble  t_pmp,dt,Jdet,scalar_ocean,pressure;
    541         IssmDouble *xyz_list_base = NULL;
    542 
    543         /*Get basal element*/
    544         if(!element->IsOnBase() || !element->IsFloating()) return NULL;
     615}/*}}}*/
     616void           ThermalAnalysis::GetBAdvecprime(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
     617        /*Compute B  matrix. B=[B1 B2 B3 B4 B5 B6] where Bi is of size 5*NDOF1.
     618         * For node i, Bi' can be expressed in the actual coordinate system
     619         * by:
     620         *       Biprime_advec=[ dh/dx ]
     621         *                     [ dh/dy ]
     622         *                     [ dh/dz ]
     623         * where h is the interpolation function for node i.
     624         *
     625         * We assume B has been allocated already, of size: 3x(NDOF1*numnodes)
     626         */
    545627
    546628        /*Fetch number of nodes for this finite element*/
    547629        int numnodes = element->GetNumberOfNodes();
    548630
    549         /*Initialize vectors*/
    550         ElementVector* pe    = element->NewElementVector();
    551         IssmDouble*    basis = xNew<IssmDouble>(numnodes);
    552 
    553         /*Retrieve all inputs and parameters*/
    554         element->GetVerticesCoordinatesBase(&xyz_list_base);
    555         element->FindParam(&dt,TimesteppingTimeStepEnum);
    556         Input*      pressure_input=element->GetInput(PressureEnum); _assert_(pressure_input);
    557         IssmDouble  gravity             = element->GetMaterialParameter(ConstantsGEnum);
    558         IssmDouble  rho_water           = element->GetMaterialParameter(MaterialsRhoSeawaterEnum);
    559         IssmDouble  rho_ice             = element->GetMaterialParameter(MaterialsRhoIceEnum);
    560         IssmDouble  heatcapacity        = element->GetMaterialParameter(MaterialsHeatcapacityEnum);
    561         IssmDouble  mixed_layer_capacity= element->GetMaterialParameter(MaterialsMixedLayerCapacityEnum);
    562         IssmDouble  thermal_exchange_vel= element->GetMaterialParameter(MaterialsThermalExchangeVelocityEnum);
    563 
    564         /* Start  looping on the number of gaussian points: */
    565         Gauss* gauss=element->NewGaussBase(2);
    566         for(int ig=gauss->begin();ig<gauss->end();ig++){
    567                 gauss->GaussPoint(ig);
    568 
    569                 element->JacobianDeterminantBase(&Jdet,xyz_list_base,gauss);
    570                 element->NodalFunctions(basis,gauss);
    571 
    572                 pressure_input->GetInputValue(&pressure,gauss);
    573                 t_pmp=element->TMeltingPoint(pressure);
    574 
    575                 scalar_ocean=gauss->weight*Jdet*rho_water*mixed_layer_capacity*thermal_exchange_vel*(t_pmp)/(heatcapacity*rho_ice);
    576                 if(reCast<bool,IssmDouble>(dt)) scalar_ocean=dt*scalar_ocean;
    577 
    578                 for(int i=0;i<numnodes;i++) pe->values[i]+=scalar_ocean*basis[i];
    579         }
    580 
    581         /*Clean up and return*/
    582         delete gauss;
    583         xDelete<IssmDouble>(basis);
    584         xDelete<IssmDouble>(xyz_list_base);
    585         return pe;
    586 }/*}}}*/
    587 void ThermalAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
    588         element->GetSolutionFromInputsOneDof(solution,TemperatureEnum);
    589 }/*}}}*/
    590 void ThermalAnalysis::GetBConduct(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
     631        /*Get nodal functions derivatives*/
     632        IssmDouble* dbasis=xNew<IssmDouble>(3*numnodes);
     633        element->NodalFunctionsDerivatives(dbasis,xyz_list,gauss);
     634
     635        /*Build B: */
     636        for(int i=0;i<numnodes;i++){
     637                B[numnodes*0+i] = dbasis[0*numnodes+i];
     638                B[numnodes*1+i] = dbasis[1*numnodes+i];
     639                B[numnodes*2+i] = dbasis[2*numnodes+i];
     640        }
     641
     642        /*Clean-up*/
     643        xDelete<IssmDouble>(dbasis);
     644}/*}}}*/
     645void           ThermalAnalysis::GetBConduct(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
    591646        /*Compute B  matrix. B=[B1 B2 B3 B4 B5 B6] where Bi is of size 5*NDOF1.
    592647         * For node i, Bi' can be expressed in the actual coordinate system
     
    617672        xDelete<IssmDouble>(dbasis);
    618673}/*}}}*/
    619 void ThermalAnalysis::GetBAdvec(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
    620         /*Compute B  matrix. B=[B1 B2 B3 B4 B5 B6] where Bi is of size 5*NDOF1.
    621          * For node i, Bi' can be expressed in the actual coordinate system
    622          * by:
    623          *       Bi_advec =[ h ]
    624          *                 [ h ]
    625          *                 [ h ]
    626          * where h is the interpolation function for node i.
    627          *
    628          * We assume B has been allocated already, of size: 3x(NDOF1*NUMNODESP1)
    629          */
    630 
    631         /*Fetch number of nodes for this finite element*/
    632         int numnodes = element->GetNumberOfNodes();
    633 
    634         /*Get nodal functions*/
    635         IssmDouble* basis=xNew<IssmDouble>(numnodes);
    636         element->NodalFunctions(basis,gauss);
    637 
    638         /*Build B: */
    639         for(int i=0;i<numnodes;i++){
    640                 B[numnodes*0+i] = basis[i];
    641                 B[numnodes*1+i] = basis[i];
    642                 B[numnodes*2+i] = basis[i];
    643         }
    644 
    645         /*Clean-up*/
    646         xDelete<IssmDouble>(basis);
    647 }/*}}}*/
    648 void ThermalAnalysis::GetBAdvecprime(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
    649         /*Compute B  matrix. B=[B1 B2 B3 B4 B5 B6] where Bi is of size 5*NDOF1.
    650          * For node i, Bi' can be expressed in the actual coordinate system
    651          * by:
    652          *       Biprime_advec=[ dh/dx ]
    653          *                     [ dh/dy ]
    654          *                     [ dh/dz ]
    655          * where h is the interpolation function for node i.
    656          *
    657          * We assume B has been allocated already, of size: 3x(NDOF1*numnodes)
    658          */
    659 
    660         /*Fetch number of nodes for this finite element*/
    661         int numnodes = element->GetNumberOfNodes();
    662 
    663         /*Get nodal functions derivatives*/
    664         IssmDouble* dbasis=xNew<IssmDouble>(3*numnodes);
    665         element->NodalFunctionsDerivatives(dbasis,xyz_list,gauss);
    666 
    667         /*Build B: */
    668         for(int i=0;i<numnodes;i++){
    669                 B[numnodes*0+i] = dbasis[0*numnodes+i];
    670                 B[numnodes*1+i] = dbasis[1*numnodes+i];
    671                 B[numnodes*2+i] = dbasis[2*numnodes+i];
    672         }
    673 
    674         /*Clean-up*/
    675         xDelete<IssmDouble>(dbasis);
    676 }/*}}}*/
    677 void ThermalAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
     674void           ThermalAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
     675        element->GetSolutionFromInputsOneDof(solution,TemperatureEnum);
     676}/*}}}*/
     677void           ThermalAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
    678678        _error_("Not implemented yet");
    679679}/*}}}*/
    680 void ThermalAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
     680void           ThermalAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
    681681
    682682        bool        converged;
     
    758758        xDelete<int>(doflist);
    759759}/*}}}*/
    760 void ThermalAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
     760void           ThermalAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
    761761
    762762        bool islevelset;
  • issm/trunk-jpl/src/c/analyses/ThermalAnalysis.h

    r18057 r18930  
    1313        public:
    1414                /*Model processing*/
    15                 int  DofsPerNode(int** doflist,int domaintype,int approximation);
    16                 void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);
    17                 void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);
    18                 void CreateNodes(Nodes* nodes,IoModel* iomodel);
    1915                void CreateConstraints(Constraints* constraints,IoModel* iomodel);
    2016                void CreateLoads(Loads* loads, IoModel* iomodel);
     17                void CreateNodes(Nodes* nodes,IoModel* iomodel);
     18                int  DofsPerNode(int** doflist,int domaintype,int approximation);
     19                void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);
     20                void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);
    2121
    2222                /*Finite element Analysis*/
     
    2525                ElementMatrix* CreateJacobianMatrix(Element* element);
    2626                ElementMatrix* CreateKMatrix(Element* element);
     27                ElementMatrix* CreateKMatrixShelf(Element* element);
    2728                ElementMatrix* CreateKMatrixVolume(Element* element);
    28                 ElementMatrix* CreateKMatrixShelf(Element* element);
    2929                ElementVector* CreatePVector(Element* element);
    30                 ElementVector* CreatePVectorVolume(Element* element);
    3130                ElementVector* CreatePVectorSheet(Element* element);
    3231                ElementVector* CreatePVectorShelf(Element* element);
    33                 void GetBConduct(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss);
    34                 void GetBAdvec(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss);
    35                 void GetBAdvecprime(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss);
    36                 void GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);
    37                 void GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);
    38                 void InputUpdateFromSolution(IssmDouble* solution,Element* element);
    39                 void UpdateConstraints(FemModel* femmodel);
     32                ElementVector* CreatePVectorVolume(Element* element);
     33                void           GetBAdvec(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss);
     34                void           GetBAdvecprime(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss);
     35                void           GetBConduct(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss);
     36                void           GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);
     37                void           GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);
     38                void           InputUpdateFromSolution(IssmDouble* solution,Element* element);
     39                void           UpdateConstraints(FemModel* femmodel);
    4040};
    4141#endif
  • issm/trunk-jpl/src/c/analyses/UzawaPressureAnalysis.cpp

    r18654 r18930  
    66
    77/*Model processing*/
     8void UzawaPressureAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
     9        return;
     10}/*}}}*/
     11void UzawaPressureAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
     12        return;
     13}/*}}}*/
     14void UzawaPressureAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
     15
     16        int finiteelement;
     17        int fe_FS;
     18
     19        iomodel->Constant(&fe_FS,FlowequationFeFSEnum);
     20        if(fe_FS==LATaylorHoodEnum) finiteelement = P1Enum;
     21        else if(fe_FS==LACrouzeixRaviartEnum) finiteelement = P1DGEnum;
     22        else _error_("solution not supported yet");
     23
     24        ::CreateNodes(nodes,iomodel,UzawaPressureAnalysisEnum,finiteelement);
     25}/*}}}*/
    826int  UzawaPressureAnalysis::DofsPerNode(int** doflist,int domaintype,int approximation){/*{{{*/
    927        return 1;
    10 }/*}}}*/
    11 void UzawaPressureAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
    12 
    13         parameters->AddObject(iomodel->CopyConstantObject(AugmentedLagrangianRhopEnum));
    14         parameters->AddObject(iomodel->CopyConstantObject(AugmentedLagrangianRholambdaEnum));
    1528}/*}}}*/
    1629void UzawaPressureAnalysis::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/
     
    4053        InputUpdateFromConstantx(elements,0.,SigmaNNEnum);
    4154}/*}}}*/
    42 void UzawaPressureAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
    43 
    44         int finiteelement;
    45         int fe_FS;
    46 
    47         iomodel->Constant(&fe_FS,FlowequationFeFSEnum);
    48         if(fe_FS==LATaylorHoodEnum) finiteelement = P1Enum;
    49         else if(fe_FS==LACrouzeixRaviartEnum) finiteelement = P1DGEnum;
    50         else _error_("solution not supported yet");
    51 
    52         ::CreateNodes(nodes,iomodel,UzawaPressureAnalysisEnum,finiteelement);
    53 }/*}}}*/
    54 void UzawaPressureAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
    55         return;
    56 }/*}}}*/
    57 void UzawaPressureAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
    58         return;
     55void UzawaPressureAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
     56
     57        parameters->AddObject(iomodel->CopyConstantObject(AugmentedLagrangianRhopEnum));
     58        parameters->AddObject(iomodel->CopyConstantObject(AugmentedLagrangianRholambdaEnum));
    5959}/*}}}*/
    6060
     
    164164        return pe;
    165165}/*}}}*/
    166 void UzawaPressureAnalysis::GetM(IssmDouble* M,Element* element,Gauss* gauss){/*{{{*/
     166void           UzawaPressureAnalysis::GetM(IssmDouble* M,Element* element,Gauss* gauss){/*{{{*/
    167167        /*Compute B  matrix. M=[M1 M2 M3] */
    168168
     
    182182        xDelete<IssmDouble>(basis);
    183183}/*}}}*/
    184 void UzawaPressureAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
     184void           UzawaPressureAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
    185185        _error_("not implemented yet");
    186186}/*}}}*/
    187 void UzawaPressureAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
     187void           UzawaPressureAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
    188188        _error_("Not implemented yet");
    189189}/*}}}*/
    190 void UzawaPressureAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
     190void           UzawaPressureAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
    191191
    192192        int        dim;
     
    297297        xDelete<int>(doflist);
    298298}/*}}}*/
    299 void UzawaPressureAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
     299void           UzawaPressureAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
    300300        /*Default, do nothing*/
    301301        return;
  • issm/trunk-jpl/src/c/analyses/UzawaPressureAnalysis.h

    r18179 r18930  
    1313        public:
    1414                /*Model processing*/
    15                 int  DofsPerNode(int** doflist,int domaintype,int approximation);
    16                 void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);
    17                 void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);
    18                 void CreateNodes(Nodes* nodes,IoModel* iomodel);
    1915                void CreateConstraints(Constraints* constraints,IoModel* iomodel);
    2016                void CreateLoads(Loads* loads, IoModel* iomodel);
     17                void CreateNodes(Nodes* nodes,IoModel* iomodel);
     18                int  DofsPerNode(int** doflist,int domaintype,int approximation);
     19                void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);
     20                void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);
    2121
    2222                /*Finite element Analysis*/
     
    2626                ElementMatrix* CreateKMatrix(Element* element);
    2727                ElementVector* CreatePVector(Element* element);
    28                 void GetM(IssmDouble* M,Element* element,Gauss* gauss);
    29                 void GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);
    30                 void GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);
    31                 void InputUpdateFromSolution(IssmDouble* solution,Element* element);
    32                 void UpdateConstraints(FemModel* femmodel);
     28                void           GetM(IssmDouble* M,Element* element,Gauss* gauss);
     29                void           GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);
     30                void           GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);
     31                void           InputUpdateFromSolution(IssmDouble* solution,Element* element);
     32                void           UpdateConstraints(FemModel* femmodel);
    3333};
    3434#endif
Note: See TracChangeset for help on using the changeset viewer.