Changeset 4285


Ignore:
Timestamp:
06/28/10 23:22:14 (15 years ago)
Author:
Eric.Larour
Message:

Cleanup of Tria, Sing and Beam elements + New flags to stop cores from creating too many results

Location:
issm/trunk/src/c
Files:
24 edited

Legend:

Unmodified
Added
Removed
  • issm/trunk/src/c/modules/ModelProcessorx/CreateDataSets.cpp

    r4218 r4285  
    5858
    5959                case SlopeAnalysisEnum:
     60                        CreateNodesSlopeCompute(pnodes, iomodel,iomodel_handle);
     61                        CreateConstraintsSlopeCompute(pconstraints,iomodel,iomodel_handle);
     62                        CreateLoadsSlopeCompute(ploads,iomodel,iomodel_handle);
     63                        UpdateElementsSlopeCompute(elements,iomodel,iomodel_handle,analysis_counter,analysis_type);
     64                        break;
     65               
     66                case BedSlopeAnalysisEnum:
     67                        CreateNodesSlopeCompute(pnodes, iomodel,iomodel_handle);
     68                        CreateConstraintsSlopeCompute(pconstraints,iomodel,iomodel_handle);
     69                        CreateLoadsSlopeCompute(ploads,iomodel,iomodel_handle);
     70                        UpdateElementsSlopeCompute(elements,iomodel,iomodel_handle,analysis_counter,analysis_type);
     71                        break;
     72
     73                case SurfaceSlopeAnalysisEnum:
    6074                        CreateNodesSlopeCompute(pnodes, iomodel,iomodel_handle);
    6175                        CreateConstraintsSlopeCompute(pconstraints,iomodel,iomodel_handle);
  • issm/trunk/src/c/objects/Elements/Penta.cpp

    r4280 r4285  
    324324                InputUpdateFromSolutionDiagnosticStokes( solution);
    325325        }
    326         else if (analysis_type==SlopeAnalysisEnum){
     326        else if (analysis_type==BedSlopeAnalysisEnum || analysis_type==SurfaceSlopeAnalysisEnum){
    327327                InputUpdateFromSolutionSlopeCompute( solution);
    328328        }
     
    664664                CreateKMatrixDiagnosticStokes( Kgg);
    665665        }
    666         else if (analysis_type==SlopeAnalysisEnum){
     666        else if (analysis_type==BedSlopeAnalysisEnum || analysis_type==SurfaceSlopeAnalysisEnum){
    667667                CreateKMatrixSlopeCompute( Kgg);
    668668        }
     
    714714                CreatePVectorDiagnosticStokes( pg);
    715715        }
    716         else if (analysis_type==SlopeAnalysisEnum){
     716        else if (analysis_type==BedSlopeAnalysisEnum || analysis_type==SurfaceSlopeAnalysisEnum){
    717717                CreatePVectorSlopeCompute( pg);
    718718        }
  • issm/trunk/src/c/objects/Elements/Sing.cpp

    r4248 r4285  
    3131}
    3232/*}}}*/
    33 /*FUNCTION void Sing::Update(int index, IoModel* iomodel,int analysis_counter,int analysis_type);{{{1*/
    34 void Sing::Update(int index, IoModel* iomodel,int analysis_counter,int analysis_type){
    35         ISSMERROR(" not supported yet!");
    36 }
    37 /*}}}*/
    3833
    3934/*Object virtual functions definitions: */
     35/*FUNCTION Sing::copy {{{1*/
     36Object* Sing::copy() {
     37
     38        int i;
     39        Sing* sing=NULL;
     40
     41        sing=new Sing();
     42
     43        /*copy fields: */
     44        sing->id=this->id;
     45        if(this->inputs){
     46                sing->inputs=(Inputs*)this->inputs->Copy();
     47        }
     48        else{
     49                sing->inputs=new Inputs();
     50        }
     51        /*point parameters: */
     52        sing->parameters=this->parameters;
     53
     54        /*pointers: */
     55        sing->node=this->node;
     56        sing->matice=this->matice;
     57        sing->matpar=this->matpar;
     58
     59        return sing;
     60}
     61/*}}}*/
     62/*FUNCTION Sing::DeepEcho {{{1*/
     63void Sing::DeepEcho(void){
     64
     65        printf("Sing:\n");
     66        printf("   id: %i\n",id);
     67        node->DeepEcho();
     68        matice->DeepEcho();
     69        matpar->DeepEcho();
     70        printf("   parameters\n");
     71        parameters->DeepEcho();
     72        printf("   inputs\n");
     73        inputs->DeepEcho();
     74
     75        return;
     76}
     77/*}}}*/
     78/*FUNCTION Sing::Demarshall {{{1*/
     79void  Sing::Demarshall(char** pmarshalled_dataset){
     80        ISSMERROR(" not supported yet!");
     81}
     82/*}}}*/
    4083/*FUNCTION Sing::Echo{{{1*/
    4184
     
    5396}
    5497/*}}}*/
    55 /*FUNCTION Sing::DeepEcho {{{1*/
    56 void Sing::DeepEcho(void){
    57 
    58         printf("Sing:\n");
    59         printf("   id: %i\n",id);
    60         node->DeepEcho();
    61         matice->DeepEcho();
    62         matpar->DeepEcho();
    63         printf("   parameters\n");
    64         parameters->DeepEcho();
    65         printf("   inputs\n");
    66         inputs->DeepEcho();
    67 
    68         return;
     98/*FUNCTION Sing::Enum {{{1*/
     99int Sing::Enum(void){
     100
     101        return SingEnum;
     102
    69103}
    70104/*}}}*/
    71105/*FUNCTION Sing::Id {{{1*/
    72106int    Sing::Id(void){ return id; }
     107/*}}}*/
     108/*FUNCTION Sing::Marshall {{{1*/
     109void  Sing::Marshall(char** pmarshalled_dataset){
     110        ISSMERROR(" not supported yet!");
     111}
     112/*}}}*/
     113/*FUNCTION Sing::MashallSize {{{1*/
     114int   Sing::MarshallSize(){
     115        ISSMERROR(" not supported yet!");
     116}
    73117/*}}}*/
    74118/*FUNCTION Sing::MyRank {{{1*/
     
    78122}
    79123/*}}}*/
    80 /*FUNCTION Sing::Marshall {{{1*/
    81 void  Sing::Marshall(char** pmarshalled_dataset){
    82         ISSMERROR(" not supported yet!");
    83 }
    84 /*}}}*/
    85 /*FUNCTION Sing::MashallSize {{{1*/
    86 int   Sing::MarshallSize(){
    87         ISSMERROR(" not supported yet!");
    88 }
    89 /*}}}*/
    90 /*FUNCTION Sing::Demarshall {{{1*/
    91 void  Sing::Demarshall(char** pmarshalled_dataset){
    92         ISSMERROR(" not supported yet!");
    93 }
    94 /*}}}*/
    95 /*FUNCTION Sing::Enum {{{1*/
    96 int Sing::Enum(void){
    97 
    98         return SingEnum;
    99 
    100 }
    101 /*}}}*/
    102 /*FUNCTION Sing::copy {{{1*/
    103 Object* Sing::copy() {
    104 
    105         int i;
    106         Sing* sing=NULL;
    107 
    108         sing=new Sing();
    109 
    110         /*copy fields: */
    111         sing->id=this->id;
    112         if(this->inputs){
    113                 sing->inputs=(Inputs*)this->inputs->Copy();
    114         }
    115         else{
    116                 sing->inputs=new Inputs();
    117         }
    118         /*point parameters: */
    119         sing->parameters=this->parameters;
    120 
    121         /*pointers: */
    122         sing->node=this->node;
    123         sing->matice=this->matice;
    124         sing->matpar=this->matpar;
    125 
    126         return sing;
    127 }
    128 /*}}}*/
    129 
    130 /*Sing management*/
     124
     125/*Update virtual functions definitions: */
     126/*FUNCTION Sing::InputUpdateFromSolution {{{1*/
     127void  Sing::InputUpdateFromSolution(double* solution){
     128        ISSMERROR(" not supported yet!");
     129}
     130/*}}}*/
     131/*FUNCTION Sing::InputUpdateFromVector(double* vector, int name, int type);{{{1*/
     132void  Sing::InputUpdateFromVector(double* vector, int name, int type){
     133
     134        /*Check that name is an element input*/
     135        if (!IsInput(name)) return;
     136
     137        switch(type){
     138
     139                case VertexEnum:
     140
     141                        /*New SingVertexInpu*/
     142                        double value;
     143
     144                        /*Get values on the 6 vertices*/
     145                        value=vector[node->GetVertexDof()];
     146
     147                        /*update input*/
     148                        this->inputs->AddInput(new SingVertexInput(name,value));
     149                        return;
     150
     151                default:
     152                        ISSMERROR("type %i (%s) not implemented yet",type,EnumAsString(type));
     153        }
     154}
     155/*}}}*/
     156/*FUNCTION Sing::InputUpdateFromVector(int* vector, int name, int type);{{{1*/
     157void  Sing::InputUpdateFromVector(int* vector, int name, int type){
     158        ISSMERROR(" not supported yet!");
     159}
     160/*}}}*/
     161/*FUNCTION Sing::InputUpdateFromVector(bool* vector, int name, int type);{{{1*/
     162void  Sing::InputUpdateFromVector(bool* vector, int name, int type){
     163        ISSMERROR(" not supported yet!");
     164}
     165/*}}}*/
     166
     167/*Element virtual functions definitions: */
     168/*FUNCTION Sing::ComputeBasalStress {{{1*/
     169void  Sing::ComputeBasalStress(Vec p_g){
     170
     171        ISSMERROR("Not implemented yet");
     172
     173}
     174/*}}}*/
     175/*FUNCTION Sing::ComputePressure {{{1*/
     176void  Sing::ComputePressure(Vec p_g){
     177
     178        int    dof;
     179        double pressure;
     180        double thickness;
     181        double rho_ice,g;
     182
     183        /*Get dof list on which we will plug the pressure values: */
     184        GetDofList1(&dof);
     185
     186        /*pressure is lithostatic: */
     187        rho_ice=matpar->GetRhoIce();
     188        g=matpar->GetG();
     189        inputs->GetParameterValue(&thickness,ThicknessEnum);
     190        pressure=rho_ice*g*thickness;
     191       
     192        /*plug local pressure values into global pressure vector: */
     193        VecSetValue(p_g,dof,pressure,INSERT_VALUES);
     194
     195}
     196/*}}}*/
     197/*FUNCTION Sing::ComputeStrainRate {{{1*/
     198void  Sing::ComputeStrainRate(Vec p_g){
     199
     200        ISSMERROR("Not implemented yet");
     201
     202}
     203/*}}}*/
    131204/*FUNCTION Sing::Configure {{{1*/
    132205void  Sing::Configure(Elements* elementsin,Loads* loadsin, DataSet* nodesin, Materials* materialsin, Parameters* parametersin){
     
    136209}
    137210/*}}}*/
     211/*FUNCTION Sing::CostFunction {{{1*/
     212double Sing::CostFunction(){
     213        ISSMERROR(" not supported yet!");
     214}
     215/*}}}*/
     216/*FUNCTION Sing::CreateKMatrix {{{1*/
     217
     218void  Sing::CreateKMatrix(Mat Kgg){
     219
     220        int analysis_type;
     221
     222        /*retrive parameters: */
     223        parameters->FindParam(&analysis_type,AnalysisTypeEnum);
     224
     225        /*Just branch to the correct element stiffness matrix generator, according to the type of analysis we are carrying out: */
     226        if (analysis_type==DiagnosticHutterAnalysisEnum){
     227                CreateKMatrixDiagnosticHutter( Kgg);
     228        }
     229        else{
     230                ISSMERROR("analysis %i (%s) not supported yet",analysis_type,EnumAsString(analysis_type));
     231        }
     232
     233}
     234/*}}}*/
     235/*FUNCTION Sing::CreatePVector {{{1*/
     236void  Sing::CreatePVector(Vec pg){
     237
     238        int analysis_type;
     239
     240        /*retrive parameters: */
     241        parameters->FindParam(&analysis_type,AnalysisTypeEnum);
     242       
     243        /*Just branch to the correct load generator, according to the type of analysis we are carrying out: */
     244        if (analysis_type==DiagnosticHutterAnalysisEnum){
     245                        CreatePVectorDiagnosticHutter( pg);
     246        }
     247        else{
     248                ISSMERROR("analysis %i (%s) not supported yet",analysis_type,EnumAsString(analysis_type));
     249        }
     250
     251}
     252/*}}}*/
     253/*FUNCTION Sing::Du {{{1*/
     254void  Sing::Du(Vec){
     255        ISSMERROR(" not supported yet!");
     256}
     257/*}}}*/
     258/*FUNCTION Sing::GetBedList {{{1*/
     259void  Sing::GetBedList(double*){
     260        ISSMERROR(" not supported yet!");
     261}
     262/*}}}*/
     263/*FUNCTION Sing::GetMatPar {{{1*/
     264void* Sing::GetMatPar(){
     265
     266        return matpar;
     267}
     268/*}}}*/
     269/*FUNCTION Sing::GetNodes {{{1*/
     270void  Sing::GetNodes(void** vpnodes){
     271       
     272        Node** pnodes=NULL;
     273
     274        /*recover nodes: */
     275        pnodes=(Node**)vpnodes;
     276
     277        pnodes[0]=node;
     278}
     279/*}}}*/
     280/*FUNCTION Sing::GetOnBed {{{1*/
     281bool   Sing::GetOnBed(){
     282        ISSMERROR(" not supported yet!");
     283}
     284/*}}}*/
     285/*FUNCTION Sing::GetShelf {{{1*/
     286bool   Sing::GetShelf(){
     287        ISSMERROR(" not supported yet!");
     288}
     289/*}}}*/
     290/*FUNCTION Sing::GetSolutionFromInputs(Vec solution);{{{1*/
     291void  Sing::GetSolutionFromInputs(Vec solution){
     292        ISSMERROR(" not supported yet!");
     293}
     294/*}}}*/
     295/*FUNCTION Sing::GetThicknessList {{{1*/
     296void  Sing::GetThicknessList(double* thickness_list){
     297        ISSMERROR(" not supported yet!");
     298}
     299/*}}}*/
     300/*FUNCTION Sing::GetVectorFromInputs(Vec vector,int NameEnum){{{1*/
     301void  Sing::GetVectorFromInputs(Vec vector,int NameEnum){
     302
     303        int i;
     304        const int numvertices=1;
     305        int doflist1[numvertices];
     306
     307        /*Find NameEnum input in the inputs dataset, and get it to fill in the vector: */
     308        for(i=0;i<this->inputs->Size();i++){
     309                Input* input=(Input*)this->inputs->GetObjectByOffset(i);
     310                if(input->EnumType()==NameEnum){
     311                        /*We found the enum.  Use its values to fill into the vector, using the vertices ids: */
     312                        this->GetDofList1(&doflist1[0]);
     313                        input->GetVectorFromInputs(vector,&doflist1[0]);
     314                        break;
     315                }
     316        }
     317}
     318/*}}}*/
     319/*FUNCTION Sing::Gradj {{{1*/
     320void  Sing::Gradj(Vec gradient,int control_type){
     321        ISSMERROR(" not supported yet!");
     322}
     323/*}}}*/
     324/*FUNCTION Sing::GradB {{{1*/
     325void  Sing::GradjB(Vec gradient){
     326        ISSMERROR(" not supported yet!");
     327}
     328/*}}}*/
     329/*FUNCTION Sing::GradjDrag {{{1*/
     330void  Sing::GradjDrag(Vec gradient){
     331        ISSMERROR(" not supported yet!");
     332}
     333/*}}}*/
     334/*FUNCTION Sing::InputAXPY(int YEnum, double scalar, int XEnum);{{{1*/
     335void  Sing::InputAXPY(int YEnum, double scalar, int XEnum){
     336
     337        Input* xinput=NULL;
     338        Input* yinput=NULL;
     339
     340        /*Find x and y inputs: */
     341        xinput=(Input*)this->inputs->GetInput(XEnum);
     342        yinput=(Input*)this->inputs->GetInput(YEnum);
     343
     344        /*some checks: */
     345        if(!xinput || !yinput)ISSMERROR("%s%s%s%s%s"," input ",EnumAsString(XEnum)," or input ",EnumAsString(YEnum)," could not be found!");
     346        if(xinput->Enum()!=yinput->Enum())ISSMERROR("%s%s%s%s%s"," input ",EnumAsString(XEnum)," and input ",EnumAsString(YEnum)," are not of the same type!");
     347
     348        /*Scale: */
     349        yinput->AXPY(xinput,scalar);
     350}
     351/*}}}*/
     352/*FUNCTION Sing::InputControlConstrain(int control_type, double cm_min, double cm_max){{{1*/
     353void  Sing::InputControlConstrain(int control_type, double cm_min, double cm_max){
     354
     355        Input* input=NULL;
     356
     357        /*Find input: */
     358        input=(Input*)this->inputs->GetInput(control_type);
     359       
     360        /*Do nothing if we  don't find it: */
     361        if(!input)return;
     362
     363        /*Constrain input using cm_min and cm_max: */
     364        input->Constrain(cm_min,cm_max);
     365
     366}
     367/*}}}*/
     368/*FUNCTION Sing::InputConvergence(int* pconverged, double* eps, int* enums,int num_enums,int* criterionenums,double* criterionvalues,int num_criterionenums){{{1*/
     369void  Sing::InputConvergence(int* pconverged,double* eps, int* enums,int num_enums,int* criterionenums,double* criterionvalues,int num_criterionenums){
     370
     371        int i;
     372        Input** new_inputs=NULL;
     373        Input** old_inputs=NULL;
     374        int     converged=1;
     375
     376        new_inputs=(Input**)xmalloc(num_enums/2*sizeof(Input*)); //half the enums are for the new inputs
     377        old_inputs=(Input**)xmalloc(num_enums/2*sizeof(Input*)); //half the enums are for the old inputs
     378       
     379        for(i=0;i<num_enums/2;i++){
     380                new_inputs[i]=(Input*)this->inputs->GetInput(enums[2*i+0]);
     381                old_inputs[i]=(Input*)this->inputs->GetInput(enums[2*i+1]);
     382                if(!new_inputs[i])ISSMERROR("%s%s"," could not find input with enum ",EnumAsString(enums[2*i+0]));
     383                if(!old_inputs[i])ISSMERROR("%s%s"," could not find input with enum ",EnumAsString(enums[2*i+0]));
     384        }
     385
     386        /*ok, we've got the inputs (new and old), now loop throught the number of criterions and fill the eps array:*/
     387        for(i=0;i<num_criterionenums;i++){
     388                IsInputConverged(eps+i,new_inputs,old_inputs,num_enums/2,criterionenums[i]);
     389                if(eps[i]>criterionvalues[i]) converged=0;
     390        }
     391
     392        /*Assign output pointers:*/
     393        *pconverged=converged;
     394
     395}
     396/*}}}*/
     397/*FUNCTION Sing::InputDuplicate(int original_enum,int new_enum){{{1*/
     398void  Sing::InputDuplicate(int original_enum,int new_enum){
     399
     400        Input* original=NULL;
     401        Input* copy=NULL;
     402
     403        /*Make a copy of the original input: */
     404        original=(Input*)this->inputs->GetInput(original_enum);
     405        copy=(Input*)original->copy();
     406
     407        /*Change copy enum to reinitialized_enum: */
     408        copy->ChangeEnum(new_enum);
     409
     410        /*Add copy into inputs, it will wipe off the one already there: */
     411        inputs->AddObject((Input*)copy);
     412}
     413/*}}}*/
     414/*FUNCTION Sing::InputScale(int enum_type,double scale_factor){{{1*/
     415void  Sing::InputScale(int enum_type,double scale_factor){
     416
     417        Input* input=NULL;
     418
     419        /*Make a copy of the original input: */
     420        input=(Input*)this->inputs->GetInput(enum_type);
     421
     422        /*Scale: */
     423        input->Scale(scale_factor);
     424}
     425/*}}}*/
     426/*FUNCTION Sing::InputToResult(int enum_type,int step,double time){{{1*/
     427void  Sing::InputToResult(int enum_type,int step,double time){
     428        ISSMERROR(" not supported yet!");
     429}
     430/*}}}*/
     431/*FUNCTION Sing::MassFlux {{{1*/
     432double Sing::MassFlux( double* segment){
     433        ISSMERROR(" not supported yet!");
     434}
     435/*}}}*/
     436/*FUNCTION Sing::MaxAbsVx(double* pmaxabsvx, bool process_units);{{{1*/
     437void  Sing::MaxAbsVx(double* pmaxabsvx, bool process_units){
     438
     439        int dim;
     440        double  maxabsvx;
     441
     442        /*retrieve dim parameter: */
     443        parameters->FindParam(&dim,DimEnum);
     444
     445        /*retrive velocity values at nodes */
     446        inputs->GetParameterValue(&maxabsvx,VxEnum);
     447        maxabsvx=fabs(maxabsvx);
     448
     449        /*Assign output pointers:*/
     450        *pmaxabsvx=maxabsvx;
     451}
     452/*}}}*/
     453/*FUNCTION Sing::MaxAbsVy(double* pmaxabsvy, bool process_units);{{{1*/
     454void  Sing::MaxAbsVy(double* pmaxabsvy, bool process_units){
     455
     456        int dim;
     457        double  maxabsvy;
     458
     459        /*retrieve dim parameter: */
     460        parameters->FindParam(&dim,DimEnum);
     461
     462        /*retrive velocity values at nodes */
     463        inputs->GetParameterValue(&maxabsvy,VyEnum);
     464        maxabsvy=fabs(maxabsvy);
     465
     466        /*Assign output pointers:*/
     467        *pmaxabsvy=maxabsvy;
     468}
     469/*}}}*/
     470/*FUNCTION Sing::MaxAbsVz(double* pmaxabsvz, bool process_units);{{{1*/
     471void  Sing::MaxAbsVz(double* pmaxabsvz, bool process_units){
     472
     473        int dim;
     474        double  maxabsvz;
     475
     476        /*retrieve dim parameter: */
     477        parameters->FindParam(&dim,DimEnum);
     478
     479        /*retrive velocity values at nodes */
     480        inputs->GetParameterValue(&maxabsvz,VzEnum);
     481        maxabsvz=fabs(maxabsvz);
     482
     483        /*Assign output pointers:*/
     484        *pmaxabsvz=maxabsvz;
     485}
     486/*}}}*/
     487/*FUNCTION Sing::MaxVel(double* pmaxvel, bool process_units);{{{1*/
     488void  Sing::MaxVel(double* pmaxvel, bool process_units){
     489
     490        int dim;
     491        double  vx;
     492        double  vy;
     493        double  vz;
     494        double  maxvel;
     495
     496        /*retrive velocity values at nodes */
     497        inputs->GetParameterValue(&vx,VxEnum);
     498        inputs->GetParameterValue(&vy,VyEnum);
     499        if(dim==3)inputs->GetParameterValue(&vz,VzEnum);
     500
     501        /*now, compute maximum of velocity :*/
     502        if(dim==2){
     503                maxvel=sqrt(pow(vx,2)+pow(vy,2));
     504        }
     505        else{
     506                maxvel=sqrt(pow(vx,2)+pow(vy,2)+pow(vz,2));
     507        }
     508
     509        /*Assign output pointers:*/
     510        *pmaxvel=maxvel;
     511
     512}
     513/*}}}*/
     514/*FUNCTION Sing::MaxVx(double* pmaxvx, bool process_units);{{{1*/
     515void  Sing::MaxVx(double* pmaxvx, bool process_units){
     516
     517        int dim;
     518        double  maxvx;
     519
     520        /*retrieve dim parameter: */
     521        parameters->FindParam(&dim,DimEnum);
     522
     523        /*retrive velocity values at nodes */
     524        inputs->GetParameterValue(&maxvx,VxEnum);
     525
     526        /*Assign output pointers:*/
     527        *pmaxvx=maxvx;
     528
     529}
     530/*}}}*/
     531/*FUNCTION Sing::MaxVy(double* pmaxvy, bool process_units);{{{1*/
     532void  Sing::MaxVy(double* pmaxvy, bool process_units){
     533
     534        int dim;
     535        double  maxvy;
     536
     537        /*retrieve dim parameter: */
     538        parameters->FindParam(&dim,DimEnum);
     539
     540        /*retrive velocity values at nodes */
     541        inputs->GetParameterValue(&maxvy,VyEnum);
     542
     543        /*Assign output pointers:*/
     544        *pmaxvy=maxvy;
     545
     546}
     547/*}}}*/
     548/*FUNCTION Sing::MaxVz(double* pmaxvz, bool process_units);{{{1*/
     549void  Sing::MaxVz(double* pmaxvz, bool process_units){
     550
     551        int dim;
     552        double  maxvz;
     553
     554        /*retrieve dim parameter: */
     555        parameters->FindParam(&dim,DimEnum);
     556
     557        /*retrive velocity values at nodes */
     558        inputs->GetParameterValue(&maxvz,VzEnum);
     559
     560        /*Assign output pointers:*/
     561        *pmaxvz=maxvz;
     562
     563}
     564/*}}}*/
     565/*FUNCTION Sing::MinVel(double* pminvel, bool process_units);{{{1*/
     566void  Sing::MinVel(double* pminvel, bool process_units){
     567
     568        int dim;
     569        double  vx;
     570        double  vy;
     571        double  vz;
     572        double  minvel;
     573
     574        /*retrive velocity values at nodes */
     575        inputs->GetParameterValue(&vx,VxEnum);
     576        inputs->GetParameterValue(&vy,VyEnum);
     577        if(dim==3)inputs->GetParameterValue(&vz,VzEnum);
     578
     579        /*now, compute minimum of velocity :*/
     580        if(dim==2){
     581                minvel=sqrt(pow(vx,2)+pow(vy,2));
     582        }
     583        else{
     584                minvel=sqrt(pow(vx,2)+pow(vy,2)+pow(vz,2));
     585        }
     586
     587        /*Assign output pointers:*/
     588        *pminvel=minvel;
     589
     590}
     591/*}}}*/
     592/*FUNCTION Sing::MinVx(double* pminvx, bool process_units);{{{1*/
     593void  Sing::MinVx(double* pminvx, bool process_units){
     594
     595        int dim;
     596        double  minvx;
     597
     598        /*retrieve dim parameter: */
     599        parameters->FindParam(&dim,DimEnum);
     600
     601        /*retrive velocity values at nodes */
     602        inputs->GetParameterValue(&minvx,VxEnum);
     603
     604        /*Assign output pointers:*/
     605        *pminvx=minvx;
     606
     607}
     608/*}}}*/
     609/*FUNCTION Sing::MinVy(double* pminvy, bool process_units);{{{1*/
     610void  Sing::MinVy(double* pminvy, bool process_units){
     611
     612        int dim;
     613        double  minvy;
     614
     615        /*retrieve dim parameter: */
     616        parameters->FindParam(&dim,DimEnum);
     617
     618        /*retrive velocity values at nodes */
     619        inputs->GetParameterValue(&minvy,VyEnum);
     620
     621        /*Assign output pointers:*/
     622        *pminvy=minvy;
     623
     624}
     625/*}}}*/
     626/*FUNCTION Sing::MinVz(double* pminvz, bool process_units);{{{1*/
     627void  Sing::MinVz(double* pminvz, bool process_units){
     628
     629        int dim;
     630        double  minvz;
     631
     632        /*retrieve dim parameter: */
     633        parameters->FindParam(&dim,DimEnum);
     634
     635        /*retrive velocity values at nodes */
     636        inputs->GetParameterValue(&minvz,VzEnum);
     637
     638        /*Assign output pointers:*/
     639        *pminvz=minvz;
     640
     641}
     642/*}}}*/
     643/*FUNCTION Sing::Misfit {{{1*/
     644double Sing::Misfit(void){
     645        ISSMERROR(" not supported yet!");
     646}
     647/*}}}*/
     648/*FUNCTION Sing::PatchFill(int* pcount, Patch* patch){{{1*/
     649void  Sing::PatchFill(int* pcount, Patch* patch){
     650       
     651        ISSMERROR(" not supported yet!");
     652}
     653/*}}}*/
     654/*FUNCTION Sing::PatchSize(int* pnumrows, int* pnumvertices,int* pnumnodes){{{1*/
     655void  Sing::PatchSize(int* pnumrows, int* pnumvertices,int* pnumnodes){
     656
     657        ISSMERROR(" not supported yet!");
     658       
     659}
     660/*}}}*/
     661/*FUNCTION Sing::ProcessResultsUnits(void){{{1*/
     662void  Sing::ProcessResultsUnits(void){
     663        ISSMERROR(" not supported yet!");
     664}
     665/*}}}*/
     666/*FUNCTION Sing::SurfaceArea {{{1*/
     667double Sing::SurfaceArea( void){
     668        ISSMERROR(" not supported yet!");
     669}
     670/*}}}*/
     671/*FUNCTION Sing::Update(int index, IoModel* iomodel,int analysis_counter,int analysis_type);{{{1*/
     672void Sing::Update(int index, IoModel* iomodel,int analysis_counter,int analysis_type){
     673        ISSMERROR(" not supported yet!");
     674}
     675/*}}}*/
     676
     677/*Sing specific routines: */
    138678/*FUNCTION Sing::IsInput{{{1*/
    139679bool Sing::IsInput(int name){
     
    143683        }
    144684        else return false;
    145 }
    146 /*}}}*/
    147 /*FUNCTION Sing::InputUpdateFromSolution {{{1*/
    148 void  Sing::InputUpdateFromSolution(double* solution){
    149         ISSMERROR(" not supported yet!");
    150 }
    151 /*}}}*/
    152 /*FUNCTION Sing::GetSolutionFromInputs(Vec solution);{{{1*/
    153 void  Sing::GetSolutionFromInputs(Vec solution){
    154         ISSMERROR(" not supported yet!");
    155 }
    156 /*}}}*/
    157 /*FUNCTION Sing::InputToResult(int enum_type,int step,double time){{{1*/
    158 void  Sing::InputToResult(int enum_type,int step,double time){
    159         ISSMERROR(" not supported yet!");
    160 }
    161 /*}}}*/
    162 /*FUNCTION Sing::ProcessResultsUnits(void){{{1*/
    163 void  Sing::ProcessResultsUnits(void){
    164         ISSMERROR(" not supported yet!");
    165 }
    166 /*}}}*/
    167                
    168 /*Sing functions*/
    169 /*FUNCTION Sing::ComputeBasalStress {{{1*/
    170 void  Sing::ComputeBasalStress(Vec p_g){
    171 
    172         ISSMERROR("Not implemented yet");
    173 
    174 }
    175 /*}}}*/
    176 /*FUNCTION Sing::ComputePressure {{{1*/
    177 void  Sing::ComputePressure(Vec p_g){
    178 
    179         int    dof;
    180         double pressure;
    181         double thickness;
    182         double rho_ice,g;
    183 
    184         /*Get dof list on which we will plug the pressure values: */
    185         GetDofList1(&dof);
    186 
    187         /*pressure is lithostatic: */
    188         rho_ice=matpar->GetRhoIce();
    189         g=matpar->GetG();
    190         inputs->GetParameterValue(&thickness,ThicknessEnum);
    191         pressure=rho_ice*g*thickness;
    192        
    193         /*plug local pressure values into global pressure vector: */
    194         VecSetValue(p_g,dof,pressure,INSERT_VALUES);
    195 
    196 }
    197 /*}}}*/
    198 /*FUNCTION Sing::ComputeStrainRate {{{1*/
    199 void  Sing::ComputeStrainRate(Vec p_g){
    200 
    201         ISSMERROR("Not implemented yet");
    202 
    203 }
    204 /*}}}*/
    205 /*FUNCTION Sing::CostFunction {{{1*/
    206 double Sing::CostFunction(){
    207         ISSMERROR(" not supported yet!");
    208 }
    209 /*}}}*/
    210 /*FUNCTION Sing::CreateKMatrix {{{1*/
    211 
    212 void  Sing::CreateKMatrix(Mat Kgg){
    213 
    214         int analysis_type;
    215 
    216         /*retrive parameters: */
    217         parameters->FindParam(&analysis_type,AnalysisTypeEnum);
    218 
    219         /*Just branch to the correct element stiffness matrix generator, according to the type of analysis we are carrying out: */
    220         if (analysis_type==DiagnosticHutterAnalysisEnum){
    221                 CreateKMatrixDiagnosticHutter( Kgg);
    222         }
    223         else{
    224                 ISSMERROR("analysis %i (%s) not supported yet",analysis_type,EnumAsString(analysis_type));
    225         }
    226 
    227685}
    228686/*}}}*/
     
    246704
    247705        MatSetValues(Kgg,numdofs,doflist,numdofs,doflist,(const double*)Ke_gg,ADD_VALUES);
    248 
    249 }
    250 /*}}}*/
    251 /*FUNCTION Sing::CreatePVector {{{1*/
    252 void  Sing::CreatePVector(Vec pg){
    253 
    254         int analysis_type;
    255 
    256         /*retrive parameters: */
    257         parameters->FindParam(&analysis_type,AnalysisTypeEnum);
    258        
    259         /*Just branch to the correct load generator, according to the type of analysis we are carrying out: */
    260         if (analysis_type==DiagnosticHutterAnalysisEnum){
    261                         CreatePVectorDiagnosticHutter( pg);
    262         }
    263         else{
    264                 ISSMERROR("analysis %i (%s) not supported yet",analysis_type,EnumAsString(analysis_type));
    265         }
    266706
    267707}
     
    317757}
    318758/*}}}*/
    319 /*FUNCTION Sing::Du {{{1*/
    320 void  Sing::Du(Vec){
    321         ISSMERROR(" not supported yet!");
    322 }
    323 /*}}}*/
    324 /*FUNCTION Sing::GetBedList {{{1*/
    325 void  Sing::GetBedList(double*){
    326         ISSMERROR(" not supported yet!");
    327 }
    328 /*}}}*/
    329759/*FUNCTION Sing::GetDofList {{{1*/
    330760void  Sing::GetDofList(int* doflist,int* pnumberofdofspernode){
     
    352782}
    353783/*}}}*/
    354 /*FUNCTION Sing::GetMatPar {{{1*/
    355 void* Sing::GetMatPar(){
    356 
    357         return matpar;
    358 }
    359 /*}}}*/
    360 /*FUNCTION Sing::GetNodes {{{1*/
    361 void  Sing::GetNodes(void** vpnodes){
    362        
    363         Node** pnodes=NULL;
    364 
    365         /*recover nodes: */
    366         pnodes=(Node**)vpnodes;
    367 
    368         pnodes[0]=node;
    369 }
    370 /*}}}*/
    371 /*FUNCTION Sing::GetOnBed {{{1*/
    372 bool   Sing::GetOnBed(){
    373         ISSMERROR(" not supported yet!");
    374 }
    375 /*}}}*/
    376 /*FUNCTION Sing::GetShelf {{{1*/
    377 bool   Sing::GetShelf(){
    378         ISSMERROR(" not supported yet!");
    379 }
    380 /*}}}*/
    381 /*FUNCTION Sing::GetThicknessList {{{1*/
    382 void  Sing::GetThicknessList(double* thickness_list){
    383         ISSMERROR(" not supported yet!");
    384 }
    385 /*}}}*/
    386 /*FUNCTION Sing::Gradj {{{1*/
    387 void  Sing::Gradj(Vec gradient,int control_type){
    388         ISSMERROR(" not supported yet!");
    389 }
    390 /*}}}*/
    391 /*FUNCTION Sing::GradB {{{1*/
    392 void  Sing::GradjB(Vec gradient){
    393         ISSMERROR(" not supported yet!");
    394 }
    395 /*}}}*/
    396 /*FUNCTION Sing::GradjDrag {{{1*/
    397 void  Sing::GradjDrag(Vec gradient){
    398         ISSMERROR(" not supported yet!");
    399 }
    400 /*}}}*/
    401 /*FUNCTION Sing::MassFlux {{{1*/
    402 double Sing::MassFlux( double* segment){
    403         ISSMERROR(" not supported yet!");
    404 }
    405 /*}}}*/
    406 /*FUNCTION Sing::Misfit {{{1*/
    407 double Sing::Misfit(void){
    408         ISSMERROR(" not supported yet!");
    409 }
    410 /*}}}*/
    411 /*FUNCTION Sing::SurfaceArea {{{1*/
    412 double Sing::SurfaceArea( void){
    413         ISSMERROR(" not supported yet!");
    414 }
    415 /*}}}*/
    416784/*FUNCTION Sing::SetClone {{{1*/
    417785void  Sing::SetClone(int* minranks){
     
    420788}
    421789/*}}}1*/
    422 /*FUNCTION Sing::InputUpdateFromVector(double* vector, int name, int type);{{{1*/
    423 void  Sing::InputUpdateFromVector(double* vector, int name, int type){
    424 
    425         /*Check that name is an element input*/
    426         if (!IsInput(name)) return;
    427 
    428         switch(type){
    429 
    430                 case VertexEnum:
    431 
    432                         /*New SingVertexInpu*/
    433                         double value;
    434 
    435                         /*Get values on the 6 vertices*/
    436                         value=vector[node->GetVertexDof()];
    437 
    438                         /*update input*/
    439                         this->inputs->AddInput(new SingVertexInput(name,value));
    440                         return;
    441 
    442                 default:
    443                         ISSMERROR("type %i (%s) not implemented yet",type,EnumAsString(type));
    444         }
    445 }
    446 /*}}}*/
    447 /*FUNCTION Sing::InputUpdateFromVector(int* vector, int name, int type);{{{1*/
    448 void  Sing::InputUpdateFromVector(int* vector, int name, int type){
    449         ISSMERROR(" not supported yet!");
    450 }
    451 /*}}}*/
    452 /*FUNCTION Sing::InputUpdateFromVector(bool* vector, int name, int type);{{{1*/
    453 void  Sing::InputUpdateFromVector(bool* vector, int name, int type){
    454         ISSMERROR(" not supported yet!");
    455 }
    456 /*}}}*/
    457 /*FUNCTION Sing::PatchSize(int* pnumrows, int* pnumvertices,int* pnumnodes){{{1*/
    458 void  Sing::PatchSize(int* pnumrows, int* pnumvertices,int* pnumnodes){
    459 
    460         ISSMERROR(" not supported yet!");
    461        
    462 }
    463 /*}}}*/
    464 /*FUNCTION Sing::PatchFill(int* pcount, Patch* patch){{{1*/
    465 void  Sing::PatchFill(int* pcount, Patch* patch){
    466        
    467         ISSMERROR(" not supported yet!");
    468 }
    469 /*}}}*/
    470 /*FUNCTION Sing::MinVel(double* pminvel, bool process_units);{{{1*/
    471 void  Sing::MinVel(double* pminvel, bool process_units){
    472 
    473         int dim;
    474         double  vx;
    475         double  vy;
    476         double  vz;
    477         double  minvel;
    478 
    479         /*retrive velocity values at nodes */
    480         inputs->GetParameterValue(&vx,VxEnum);
    481         inputs->GetParameterValue(&vy,VyEnum);
    482         if(dim==3)inputs->GetParameterValue(&vz,VzEnum);
    483 
    484         /*now, compute minimum of velocity :*/
    485         if(dim==2){
    486                 minvel=sqrt(pow(vx,2)+pow(vy,2));
    487         }
    488         else{
    489                 minvel=sqrt(pow(vx,2)+pow(vy,2)+pow(vz,2));
    490         }
    491 
    492         /*Assign output pointers:*/
    493         *pminvel=minvel;
    494 
    495 }
    496 /*}}}*/
    497 /*FUNCTION Sing::MaxVel(double* pmaxvel, bool process_units);{{{1*/
    498 void  Sing::MaxVel(double* pmaxvel, bool process_units){
    499 
    500         int dim;
    501         double  vx;
    502         double  vy;
    503         double  vz;
    504         double  maxvel;
    505 
    506         /*retrive velocity values at nodes */
    507         inputs->GetParameterValue(&vx,VxEnum);
    508         inputs->GetParameterValue(&vy,VyEnum);
    509         if(dim==3)inputs->GetParameterValue(&vz,VzEnum);
    510 
    511         /*now, compute maximum of velocity :*/
    512         if(dim==2){
    513                 maxvel=sqrt(pow(vx,2)+pow(vy,2));
    514         }
    515         else{
    516                 maxvel=sqrt(pow(vx,2)+pow(vy,2)+pow(vz,2));
    517         }
    518 
    519         /*Assign output pointers:*/
    520         *pmaxvel=maxvel;
    521 
    522 }
    523 /*}}}*/
    524 /*FUNCTION Sing::MinVx(double* pminvx, bool process_units);{{{1*/
    525 void  Sing::MinVx(double* pminvx, bool process_units){
    526 
    527         int dim;
    528         double  minvx;
    529 
    530         /*retrieve dim parameter: */
    531         parameters->FindParam(&dim,DimEnum);
    532 
    533         /*retrive velocity values at nodes */
    534         inputs->GetParameterValue(&minvx,VxEnum);
    535 
    536         /*Assign output pointers:*/
    537         *pminvx=minvx;
    538 
    539 }
    540 /*}}}*/
    541 /*FUNCTION Sing::MaxVx(double* pmaxvx, bool process_units);{{{1*/
    542 void  Sing::MaxVx(double* pmaxvx, bool process_units){
    543 
    544         int dim;
    545         double  maxvx;
    546 
    547         /*retrieve dim parameter: */
    548         parameters->FindParam(&dim,DimEnum);
    549 
    550         /*retrive velocity values at nodes */
    551         inputs->GetParameterValue(&maxvx,VxEnum);
    552 
    553         /*Assign output pointers:*/
    554         *pmaxvx=maxvx;
    555 
    556 }
    557 /*}}}*/
    558 /*FUNCTION Sing::MaxAbsVx(double* pmaxabsvx, bool process_units);{{{1*/
    559 void  Sing::MaxAbsVx(double* pmaxabsvx, bool process_units){
    560 
    561         int dim;
    562         double  maxabsvx;
    563 
    564         /*retrieve dim parameter: */
    565         parameters->FindParam(&dim,DimEnum);
    566 
    567         /*retrive velocity values at nodes */
    568         inputs->GetParameterValue(&maxabsvx,VxEnum);
    569         maxabsvx=fabs(maxabsvx);
    570 
    571         /*Assign output pointers:*/
    572         *pmaxabsvx=maxabsvx;
    573 }
    574 /*}}}*/
    575 /*FUNCTION Sing::MinVy(double* pminvy, bool process_units);{{{1*/
    576 void  Sing::MinVy(double* pminvy, bool process_units){
    577 
    578         int dim;
    579         double  minvy;
    580 
    581         /*retrieve dim parameter: */
    582         parameters->FindParam(&dim,DimEnum);
    583 
    584         /*retrive velocity values at nodes */
    585         inputs->GetParameterValue(&minvy,VyEnum);
    586 
    587         /*Assign output pointers:*/
    588         *pminvy=minvy;
    589 
    590 }
    591 /*}}}*/
    592 /*FUNCTION Sing::MaxVy(double* pmaxvy, bool process_units);{{{1*/
    593 void  Sing::MaxVy(double* pmaxvy, bool process_units){
    594 
    595         int dim;
    596         double  maxvy;
    597 
    598         /*retrieve dim parameter: */
    599         parameters->FindParam(&dim,DimEnum);
    600 
    601         /*retrive velocity values at nodes */
    602         inputs->GetParameterValue(&maxvy,VyEnum);
    603 
    604         /*Assign output pointers:*/
    605         *pmaxvy=maxvy;
    606 
    607 }
    608 /*}}}*/
    609 /*FUNCTION Sing::MaxAbsVy(double* pmaxabsvy, bool process_units);{{{1*/
    610 void  Sing::MaxAbsVy(double* pmaxabsvy, bool process_units){
    611 
    612         int dim;
    613         double  maxabsvy;
    614 
    615         /*retrieve dim parameter: */
    616         parameters->FindParam(&dim,DimEnum);
    617 
    618         /*retrive velocity values at nodes */
    619         inputs->GetParameterValue(&maxabsvy,VyEnum);
    620         maxabsvy=fabs(maxabsvy);
    621 
    622         /*Assign output pointers:*/
    623         *pmaxabsvy=maxabsvy;
    624 }
    625 /*}}}*/
    626 /*FUNCTION Sing::MinVz(double* pminvz, bool process_units);{{{1*/
    627 void  Sing::MinVz(double* pminvz, bool process_units){
    628 
    629         int dim;
    630         double  minvz;
    631 
    632         /*retrieve dim parameter: */
    633         parameters->FindParam(&dim,DimEnum);
    634 
    635         /*retrive velocity values at nodes */
    636         inputs->GetParameterValue(&minvz,VzEnum);
    637 
    638         /*Assign output pointers:*/
    639         *pminvz=minvz;
    640 
    641 }
    642 /*}}}*/
    643 /*FUNCTION Sing::MaxVz(double* pmaxvz, bool process_units);{{{1*/
    644 void  Sing::MaxVz(double* pmaxvz, bool process_units){
    645 
    646         int dim;
    647         double  maxvz;
    648 
    649         /*retrieve dim parameter: */
    650         parameters->FindParam(&dim,DimEnum);
    651 
    652         /*retrive velocity values at nodes */
    653         inputs->GetParameterValue(&maxvz,VzEnum);
    654 
    655         /*Assign output pointers:*/
    656         *pmaxvz=maxvz;
    657 
    658 }
    659 /*}}}*/
    660 /*FUNCTION Sing::MaxAbsVz(double* pmaxabsvz, bool process_units);{{{1*/
    661 void  Sing::MaxAbsVz(double* pmaxabsvz, bool process_units){
    662 
    663         int dim;
    664         double  maxabsvz;
    665 
    666         /*retrieve dim parameter: */
    667         parameters->FindParam(&dim,DimEnum);
    668 
    669         /*retrive velocity values at nodes */
    670         inputs->GetParameterValue(&maxabsvz,VzEnum);
    671         maxabsvz=fabs(maxabsvz);
    672 
    673         /*Assign output pointers:*/
    674         *pmaxabsvz=maxabsvz;
    675 }
    676 /*}}}*/
    677 /*FUNCTION Sing::InputDuplicate(int original_enum,int new_enum){{{1*/
    678 void  Sing::InputDuplicate(int original_enum,int new_enum){
    679 
    680         Input* original=NULL;
    681         Input* copy=NULL;
    682 
    683         /*Make a copy of the original input: */
    684         original=(Input*)this->inputs->GetInput(original_enum);
    685         copy=(Input*)original->copy();
    686 
    687         /*Change copy enum to reinitialized_enum: */
    688         copy->ChangeEnum(new_enum);
    689 
    690         /*Add copy into inputs, it will wipe off the one already there: */
    691         inputs->AddObject((Input*)copy);
    692 }
    693 /*}}}*/
    694 /*FUNCTION Sing::InputScale(int enum_type,double scale_factor){{{1*/
    695 void  Sing::InputScale(int enum_type,double scale_factor){
    696 
    697         Input* input=NULL;
    698 
    699         /*Make a copy of the original input: */
    700         input=(Input*)this->inputs->GetInput(enum_type);
    701 
    702         /*Scale: */
    703         input->Scale(scale_factor);
    704 }
    705 /*}}}*/
    706 /*FUNCTION Sing::InputAXPY(int YEnum, double scalar, int XEnum);{{{1*/
    707 void  Sing::InputAXPY(int YEnum, double scalar, int XEnum){
    708 
    709         Input* xinput=NULL;
    710         Input* yinput=NULL;
    711 
    712         /*Find x and y inputs: */
    713         xinput=(Input*)this->inputs->GetInput(XEnum);
    714         yinput=(Input*)this->inputs->GetInput(YEnum);
    715 
    716         /*some checks: */
    717         if(!xinput || !yinput)ISSMERROR("%s%s%s%s%s"," input ",EnumAsString(XEnum)," or input ",EnumAsString(YEnum)," could not be found!");
    718         if(xinput->Enum()!=yinput->Enum())ISSMERROR("%s%s%s%s%s"," input ",EnumAsString(XEnum)," and input ",EnumAsString(YEnum)," are not of the same type!");
    719 
    720         /*Scale: */
    721         yinput->AXPY(xinput,scalar);
    722 }
    723 /*}}}*/
    724 /*FUNCTION Sing::InputControlConstrain(int control_type, double cm_min, double cm_max){{{1*/
    725 void  Sing::InputControlConstrain(int control_type, double cm_min, double cm_max){
    726 
    727         Input* input=NULL;
    728 
    729         /*Find input: */
    730         input=(Input*)this->inputs->GetInput(control_type);
    731        
    732         /*Do nothing if we  don't find it: */
    733         if(!input)return;
    734 
    735         /*Constrain input using cm_min and cm_max: */
    736         input->Constrain(cm_min,cm_max);
    737 
    738 }
    739 /*}}}*/
    740 /*FUNCTION Sing::GetVectorFromInputs(Vec vector,int NameEnum){{{1*/
    741 void  Sing::GetVectorFromInputs(Vec vector,int NameEnum){
    742 
    743         int i;
    744         const int numvertices=1;
    745         int doflist1[numvertices];
    746 
    747         /*Find NameEnum input in the inputs dataset, and get it to fill in the vector: */
    748         for(i=0;i<this->inputs->Size();i++){
    749                 Input* input=(Input*)this->inputs->GetObjectByOffset(i);
    750                 if(input->EnumType()==NameEnum){
    751                         /*We found the enum.  Use its values to fill into the vector, using the vertices ids: */
    752                         this->GetDofList1(&doflist1[0]);
    753                         input->GetVectorFromInputs(vector,&doflist1[0]);
    754                         break;
    755                 }
    756         }
    757 }
    758 /*}}}*/
    759 /*FUNCTION Sing::InputConvergence(int* pconverged, double* eps, int* enums,int num_enums,int* criterionenums,double* criterionvalues,int num_criterionenums){{{1*/
    760 void  Sing::InputConvergence(int* pconverged,double* eps, int* enums,int num_enums,int* criterionenums,double* criterionvalues,int num_criterionenums){
    761 
    762         int i;
    763         Input** new_inputs=NULL;
    764         Input** old_inputs=NULL;
    765         int     converged=1;
    766 
    767         new_inputs=(Input**)xmalloc(num_enums/2*sizeof(Input*)); //half the enums are for the new inputs
    768         old_inputs=(Input**)xmalloc(num_enums/2*sizeof(Input*)); //half the enums are for the old inputs
    769        
    770         for(i=0;i<num_enums/2;i++){
    771                 new_inputs[i]=(Input*)this->inputs->GetInput(enums[2*i+0]);
    772                 old_inputs[i]=(Input*)this->inputs->GetInput(enums[2*i+1]);
    773                 if(!new_inputs[i])ISSMERROR("%s%s"," could not find input with enum ",EnumAsString(enums[2*i+0]));
    774                 if(!old_inputs[i])ISSMERROR("%s%s"," could not find input with enum ",EnumAsString(enums[2*i+0]));
    775         }
    776 
    777         /*ok, we've got the inputs (new and old), now loop throught the number of criterions and fill the eps array:*/
    778         for(i=0;i<num_criterionenums;i++){
    779                 IsInputConverged(eps+i,new_inputs,old_inputs,num_enums/2,criterionenums[i]);
    780                 if(eps[i]>criterionvalues[i]) converged=0;
    781         }
    782 
    783         /*Assign output pointers:*/
    784         *pconverged=converged;
    785 
    786 }
    787 /*}}}*/
  • issm/trunk/src/c/objects/Elements/Sing.h

    r4249 r4285  
    4242                /*}}}*/
    4343                /*Object virtual functions definitions:{{{1 */
    44                 void  Echo();
    45                 void  DeepEcho();
    46                 int   Id();
    47                 int   MyRank();
    48                 void  Marshall(char** pmarshalled_dataset);
    49                 int   MarshallSize();
    50                 void  Demarshall(char** pmarshalled_dataset);
    51                 int   Enum();
    5244                Object* copy();
     45                void    Echo();
     46                int     Id();
     47                int     MyRank();
     48                void    Marshall(char** pmarshalled_dataset);
     49                int     MarshallSize();
     50                int     Enum();
     51                void    DeepEcho();
     52                void    Demarshall(char** pmarshalled_dataset);
    5353                /*}}}*/
    5454                /*Update virtual functions resolution: {{{1*/
     55                void  InputUpdateFromConstant(bool constant, int name){ISSMERROR("Not implemented yet!");}
     56                void  InputUpdateFromConstant(double constant, int name){ISSMERROR("Not implemented yet!");}
     57                void  InputUpdateFromConstant(int constant, int name){ISSMERROR("Not implemented yet!");}
     58                void  InputUpdateFromSolution(double* solutiong);
     59                void  InputUpdateFromVector(bool* vector, int name, int type);
    5560                void  InputUpdateFromVector(double* vector, int name, int type);
    5661                void  InputUpdateFromVector(int* vector, int name, int type);
    57                 void  InputUpdateFromVector(bool* vector, int name, int type);
    58                 void  InputUpdateFromConstant(double constant, int name){ISSMERROR("Not implemented yet!");}
    59                 void  InputUpdateFromConstant(int constant, int name){ISSMERROR("Not implemented yet!");}
    60                 void  InputUpdateFromConstant(bool constant, int name){ISSMERROR("Not implemented yet!");}
    61                 void  InputUpdateFromSolution(double* solutiong);
    6262                /*}}}*/
    6363                /*Element virtual functions definitions: {{{1*/
  • issm/trunk/src/c/objects/Elements/Tria.cpp

    r4282 r4285  
    6969}
    7070/*}}}*/
    71 /*FUNCTION Tria::Update(IoModel* iomodel,int analysis_counter,int analysis_type){{{1*/
    72 void Tria::Update(int index, IoModel* iomodel,int analysis_counter,int analysis_type){ //i is the element index
    73 
    74         /*Intermediaries*/
    75         int    i;
    76         int    tria_node_ids[3];
    77         int    tria_vertex_ids[3];
    78         double nodeinputs[3];
    79 
    80         /*Checks if debuging*/
    81         /*{{{2*/
    82         ISSMASSERT(iomodel->elements);
    83         /*}}}*/
    84 
    85         /*Recover vertices ids needed to initialize inputs*/
    86         for(i=0;i<3;i++){
    87                 tria_vertex_ids[i]=(int)iomodel->elements[3*index+i]; //ids for vertices are in the elements array from Matlab
    88         }
    89 
    90         /*Recover nodes ids needed to initialize the node hook.*/
    91         if (analysis_type==Prognostic2AnalysisEnum || analysis_type==Balancedthickness2AnalysisEnum){
    92                 /*Discontinuous Galerkin*/
    93                 tria_node_ids[0]=iomodel->nodecounter+3*index+1;
    94                 tria_node_ids[1]=iomodel->nodecounter+3*index+2;
    95                 tria_node_ids[2]=iomodel->nodecounter+3*index+3;
     71
     72/*Object virtual functions definitions:*/
     73/*FUNCTION Tria::copy {{{1*/
     74Object* Tria::copy() {
     75
     76        int i;
     77        Tria* tria=NULL;
     78
     79        tria=new Tria();
     80
     81        /*copy fields: */
     82        tria->id=this->id;
     83        tria->interpolation_type=this->interpolation_type;
     84        if(this->inputs){
     85                tria->inputs=(Inputs*)this->inputs->Copy();
    9686        }
    9787        else{
    98                 /*Continuous Galerkin*/
    99                 for(i=0;i<3;i++){
    100                         tria_node_ids[i]=iomodel->nodecounter+(int)*(iomodel->elements+3*index+i); //ids for vertices are in the elements array from Matlab
    101                 }
    102         }
    103 
    104         /*hooks: */
    105         this->SetHookNodes(tria_node_ids,analysis_counter); this->nodes=NULL; //set hook to nodes, for this analysis type
     88                tria->inputs=new Inputs();
     89        }
     90        if(this->results){
     91                tria->results=(Results*)this->results->Copy();
     92        }
     93        else{
     94                tria->results=new Results();
     95        }
     96        /*point parameters: */
     97        tria->parameters=this->parameters;
     98
     99        /*now deal with hooks and objects: */
     100        tria->InitHookNodes(this->numanalyses);
     101        for(i=0;i<this->numanalyses;i++)tria->hnodes[i].copy(&this->hnodes[i]);
     102        tria->hmatice.copy(&this->hmatice);
     103        tria->hmatpar.copy(&this->hmatpar);
     104
     105        /*recover objects: */
     106        tria->nodes=(Node**)xmalloc(3*sizeof(Node*)); //we cannot rely on an analysis_counter to tell us which analysis_type we are running, so we just copy the nodes.
     107        for(i=0;i<3;i++)tria->nodes[i]=this->nodes[i];
     108        tria->matice=(Matice*)tria->hmatice.delivers();
     109        tria->matpar=(Matpar*)tria->hmatpar.delivers();
     110
     111        return tria;
     112}
     113/*}}}*/
     114/*FUNCTION Tria::DeepEcho{{{1*/
     115void Tria::DeepEcho(void){
     116
     117        printf("Tria:\n");
     118        printf("   id: %i\n",id);
     119        if(nodes){
     120                nodes[0]->DeepEcho();
     121                nodes[1]->DeepEcho();
     122                nodes[2]->DeepEcho();
     123        }
     124        else printf("nodes = NULL\n");
     125
     126        if (matice) matice->DeepEcho();
     127        else printf("matice = NULL\n");
     128
     129        if (matpar) matpar->DeepEcho();
     130        else printf("matpar = NULL\n");
     131
     132        printf("   parameters\n");
     133        if (parameters) parameters->DeepEcho();
     134        else printf("parameters = NULL\n");
     135
     136        printf("   inputs\n");
     137        if (inputs) inputs->DeepEcho();
     138        else printf("inputs=NULL\n");
     139
     140        if (results) results->DeepEcho();
     141        else printf("results=NULL\n");
    106142       
    107         /*add as many inputs per element as requested:*/
    108         if (iomodel->thickness) {
    109                 for(i=0;i<3;i++)nodeinputs[i]=iomodel->thickness[tria_vertex_ids[i]-1];
    110                 this->inputs->AddInput(new TriaVertexInput(ThicknessEnum,nodeinputs));
    111         }
    112         if (iomodel->surface) {
    113                 for(i=0;i<3;i++)nodeinputs[i]=iomodel->surface[tria_vertex_ids[i]-1];
    114                 this->inputs->AddInput(new TriaVertexInput(SurfaceEnum,nodeinputs));
    115         }
    116         if (iomodel->bed) {
    117                 for(i=0;i<3;i++)nodeinputs[i]=iomodel->bed[tria_vertex_ids[i]-1];
    118                 this->inputs->AddInput(new TriaVertexInput(BedEnum,nodeinputs));
    119         }
    120         if (iomodel->drag_coefficient) {
    121                 for(i=0;i<3;i++)nodeinputs[i]=iomodel->drag_coefficient[tria_vertex_ids[i]-1];
    122                 this->inputs->AddInput(new TriaVertexInput(DragCoefficientEnum,nodeinputs));
    123 
    124                 if (iomodel->drag_p) this->inputs->AddInput(new DoubleInput(DragPEnum,iomodel->drag_p[index]));
    125                 if (iomodel->drag_q) this->inputs->AddInput(new DoubleInput(DragQEnum,iomodel->drag_q[index]));
    126                 this->inputs->AddInput(new IntInput(DragTypeEnum,iomodel->drag_type));
    127         }
    128         if (iomodel->melting_rate) {
    129                 for(i=0;i<3;i++)nodeinputs[i]=iomodel->melting_rate[tria_vertex_ids[i]-1]/iomodel->yts;
    130                 this->inputs->AddInput(new TriaVertexInput(MeltingRateEnum,nodeinputs));
    131         }
    132         if (iomodel->accumulation_rate) {
    133                 for(i=0;i<3;i++)nodeinputs[i]=iomodel->accumulation_rate[tria_vertex_ids[i]-1]/iomodel->yts;
    134                 this->inputs->AddInput(new TriaVertexInput(AccumulationRateEnum,nodeinputs));
    135         }
    136         if (iomodel->geothermalflux) {
    137                 for(i=0;i<3;i++)nodeinputs[i]=iomodel->geothermalflux[tria_vertex_ids[i]-1];
    138                 this->inputs->AddInput(new TriaVertexInput(GeothermalFluxEnum,nodeinputs));
    139         }
    140         if (iomodel->dhdt) {
    141                 for(i=0;i<3;i++)nodeinputs[i]=iomodel->dhdt[tria_vertex_ids[i]-1];
    142                 this->inputs->AddInput(new TriaVertexInput(DhDtEnum,nodeinputs));
    143         }
    144         if (iomodel->pressure) {
    145                 for(i=0;i<3;i++)nodeinputs[i]=iomodel->pressure[tria_vertex_ids[i]-1];
    146                 this->inputs->AddInput(new TriaVertexInput(PressureEnum,nodeinputs));
    147         }
    148         if (iomodel->temperature) {
    149                 for(i=0;i<3;i++)nodeinputs[i]=iomodel->temperature[tria_vertex_ids[i]-1];
    150                 this->inputs->AddInput(new TriaVertexInput(TemperatureEnum,nodeinputs));
    151         }
    152         /*vx,vy and vz: */
    153         if (iomodel->vx) {
    154                 for(i=0;i<3;i++)nodeinputs[i]=iomodel->vx[tria_vertex_ids[i]-1]/iomodel->yts;
    155                 this->inputs->AddInput(new TriaVertexInput(VxEnum,nodeinputs));
    156                 this->inputs->AddInput(new TriaVertexInput(VxOldEnum,nodeinputs));
    157         }
    158         if (iomodel->vy) {
    159                 for(i=0;i<3;i++)nodeinputs[i]=iomodel->vy[tria_vertex_ids[i]-1]/iomodel->yts;
    160                 this->inputs->AddInput(new TriaVertexInput(VyEnum,nodeinputs));
    161                 this->inputs->AddInput(new TriaVertexInput(VyOldEnum,nodeinputs));
    162         }
    163         if (iomodel->vz) {
    164                 for(i=0;i<3;i++)nodeinputs[i]=iomodel->vz[tria_vertex_ids[i]-1]/iomodel->yts;
    165                 this->inputs->AddInput(new TriaVertexInput(VzEnum,nodeinputs));
    166                 this->inputs->AddInput(new TriaVertexInput(VzOldEnum,nodeinputs));
    167         }
    168         if (iomodel->vx_obs) {
    169                 for(i=0;i<3;i++)nodeinputs[i]=iomodel->vx_obs[tria_vertex_ids[i]-1]/iomodel->yts;
    170                 this->inputs->AddInput(new TriaVertexInput(VxObsEnum,nodeinputs));
    171         }
    172         if (iomodel->vy_obs) {
    173                 for(i=0;i<3;i++)nodeinputs[i]=iomodel->vy_obs[tria_vertex_ids[i]-1]/iomodel->yts;
    174                 this->inputs->AddInput(new TriaVertexInput(VyObsEnum,nodeinputs));
    175         }
    176         if (iomodel->vz_obs) {
    177                 for(i=0;i<3;i++)nodeinputs[i]=iomodel->vz_obs[tria_vertex_ids[i]-1]/iomodel->yts;
    178                 this->inputs->AddInput(new TriaVertexInput(VzObsEnum,nodeinputs));
    179         }
    180         if (iomodel->weights) {
    181                 for(i=0;i<3;i++)nodeinputs[i]=iomodel->weights[tria_vertex_ids[i]-1];
    182                 this->inputs->AddInput(new TriaVertexInput(WeightsEnum,nodeinputs));
    183         }
    184         if (iomodel->elementoniceshelf) this->inputs->AddInput(new BoolInput(ElementOnIceShelfEnum,(IssmBool)iomodel->elementoniceshelf[index]));
    185         if (iomodel->elementonbed) this->inputs->AddInput(new BoolInput(ElementOnBedEnum,(IssmBool)iomodel->elementonbed[index]));
    186         if (iomodel->elementonwater) this->inputs->AddInput(new BoolInput(ElementOnWaterEnum,(IssmBool)iomodel->elementonwater[index]));
    187         if (iomodel->elementonsurface) this->inputs->AddInput(new BoolInput(ElementOnSurfaceEnum,(IssmBool)iomodel->elementonsurface[index]));
    188 
    189         /*Defaults if not provided in iomodel*/
    190         switch(analysis_type){
    191 
    192                 case DiagnosticHorizAnalysisEnum: case DiagnosticVertAnalysisEnum: case DiagnosticStokesAnalysisEnum:
    193 
    194                         /*default vx,vy and vz: either observation or 0 */
    195                         if(!iomodel->vx){
    196                                 if (iomodel->vx_obs) for(i=0;i<3;i++)nodeinputs[i]=iomodel->vx_obs[tria_vertex_ids[i]-1]/iomodel->yts;
    197                                 else                 for(i=0;i<3;i++)nodeinputs[i]=0;
    198                                 this->inputs->AddInput(new TriaVertexInput(VxEnum,nodeinputs));
    199                                 this->inputs->AddInput(new TriaVertexInput(VxOldEnum,nodeinputs));
    200                         }
    201                         if(!iomodel->vy){
    202                                 if (iomodel->vy_obs) for(i=0;i<3;i++)nodeinputs[i]=iomodel->vy_obs[tria_vertex_ids[i]-1]/iomodel->yts;
    203                                 else                 for(i=0;i<3;i++)nodeinputs[i]=0;
    204                                 this->inputs->AddInput(new TriaVertexInput(VyEnum,nodeinputs));
    205                                 this->inputs->AddInput(new TriaVertexInput(VyOldEnum,nodeinputs));
    206                         }
    207                         if(!iomodel->vz){
    208                                 if (iomodel->vz_obs) for(i=0;i<3;i++)nodeinputs[i]=iomodel->vz_obs[tria_vertex_ids[i]-1]/iomodel->yts;
    209                                 else                 for(i=0;i<3;i++)nodeinputs[i]=0;
    210                                 this->inputs->AddInput(new TriaVertexInput(VzEnum,nodeinputs));
    211                                 this->inputs->AddInput(new TriaVertexInput(VzOldEnum,nodeinputs));
    212                         }
    213                         break;
    214 
    215                 default:
    216                         /*No update for other solution types*/
    217                         break;
    218 
    219         }
    220 
    221         //this->parameters: we still can't point to it, it may not even exist. Configure will handle this.
     143        return;
     144}
     145/*}}}*/
     146/*FUNCTION Tria::Demarshall {{{1*/
     147void  Tria::Demarshall(char** pmarshalled_dataset){
     148
     149        char* marshalled_dataset=NULL;
     150        int i;
     151
     152        /*recover marshalled_dataset: */
     153        marshalled_dataset=*pmarshalled_dataset;
     154
     155        /*this time, no need to get enum type, the pointer directly points to the beginning of the
     156         *object data (thanks to DataSet::Demarshall):*/
     157        memcpy(&id,marshalled_dataset,sizeof(id));marshalled_dataset+=sizeof(id);
     158        memcpy(&interpolation_type,marshalled_dataset,sizeof(interpolation_type));marshalled_dataset+=sizeof(interpolation_type);
     159        memcpy(&numanalyses,marshalled_dataset,sizeof(numanalyses));marshalled_dataset+=sizeof(numanalyses);
     160
     161        /*allocate dynamic memory: */
     162        InitHookNodes(numanalyses);
     163
     164        /*demarshall hooks: */
     165        for(i=0;i<numanalyses;i++)hnodes[i].Demarshall(&marshalled_dataset);
     166        hmatice.Demarshall(&marshalled_dataset);
     167        hmatpar.Demarshall(&marshalled_dataset);
     168
     169        /*pointers are garbabe, until configuration is carried out: */
     170        nodes=NULL;
     171        matice=NULL;
     172        matpar=NULL;
     173       
     174        /*demarshall inputs: */
     175        inputs=(Inputs*)DataSetDemarshallRaw(&marshalled_dataset);
     176        results=(Results*)DataSetDemarshallRaw(&marshalled_dataset);
     177
     178        /*parameters: may not exist even yet, so let Configure handle it: */
    222179        this->parameters=NULL;
    223180
    224 }
    225 /*}}}*/
    226 
    227 /*Object virtual functions definitions:*/
     181        /*return: */
     182        *pmarshalled_dataset=marshalled_dataset;
     183        return;
     184}
     185/*}}}*/
    228186/*FUNCTION Tria::Echo{{{1*/
    229187void Tria::Echo(void){
     
    255213}
    256214/*}}}*/
    257 /*FUNCTION Tria::DeepEcho{{{1*/
    258 void Tria::DeepEcho(void){
    259 
    260         printf("Tria:\n");
    261         printf("   id: %i\n",id);
    262         if(nodes){
    263                 nodes[0]->DeepEcho();
    264                 nodes[1]->DeepEcho();
    265                 nodes[2]->DeepEcho();
    266         }
    267         else printf("nodes = NULL\n");
    268 
    269         if (matice) matice->DeepEcho();
    270         else printf("matice = NULL\n");
    271 
    272         if (matpar) matpar->DeepEcho();
    273         else printf("matpar = NULL\n");
    274 
    275         printf("   parameters\n");
    276         if (parameters) parameters->DeepEcho();
    277         else printf("parameters = NULL\n");
    278 
    279         printf("   inputs\n");
    280         if (inputs) inputs->DeepEcho();
    281         else printf("inputs=NULL\n");
    282 
    283         if (results) results->DeepEcho();
    284         else printf("results=NULL\n");
    285        
    286         return;
     215/*FUNCTION Tria::Enum {{{1*/
     216int Tria::Enum(void){
     217
     218        return TriaEnum;
     219
    287220}
    288221/*}}}*/
    289222/*FUNCTION Tria::Id {{{1*/
    290223int    Tria::Id(){ return id; }
    291 /*}}}*/
    292 /*FUNCTION Tria::MyRank {{{1*/
    293 int    Tria::MyRank(void){
    294         extern int my_rank;
    295         return my_rank;
    296 }
    297224/*}}}*/
    298225/*FUNCTION Tria::Marshall {{{1*/
     
    366293}
    367294/*}}}*/
    368 /*FUNCTION Tria::Demarshall {{{1*/
    369 void  Tria::Demarshall(char** pmarshalled_dataset){
    370 
    371         char* marshalled_dataset=NULL;
    372         int i;
    373 
    374         /*recover marshalled_dataset: */
    375         marshalled_dataset=*pmarshalled_dataset;
    376 
    377         /*this time, no need to get enum type, the pointer directly points to the beginning of the
    378          *object data (thanks to DataSet::Demarshall):*/
    379         memcpy(&id,marshalled_dataset,sizeof(id));marshalled_dataset+=sizeof(id);
    380         memcpy(&interpolation_type,marshalled_dataset,sizeof(interpolation_type));marshalled_dataset+=sizeof(interpolation_type);
    381         memcpy(&numanalyses,marshalled_dataset,sizeof(numanalyses));marshalled_dataset+=sizeof(numanalyses);
    382 
    383         /*allocate dynamic memory: */
    384         InitHookNodes(numanalyses);
    385 
    386         /*demarshall hooks: */
    387         for(i=0;i<numanalyses;i++)hnodes[i].Demarshall(&marshalled_dataset);
    388         hmatice.Demarshall(&marshalled_dataset);
    389         hmatpar.Demarshall(&marshalled_dataset);
    390 
    391         /*pointers are garbabe, until configuration is carried out: */
    392         nodes=NULL;
    393         matice=NULL;
    394         matpar=NULL;
    395        
    396         /*demarshall inputs: */
    397         inputs=(Inputs*)DataSetDemarshallRaw(&marshalled_dataset);
    398         results=(Results*)DataSetDemarshallRaw(&marshalled_dataset);
    399 
    400         /*parameters: may not exist even yet, so let Configure handle it: */
    401         this->parameters=NULL;
    402 
    403         /*return: */
    404         *pmarshalled_dataset=marshalled_dataset;
    405         return;
    406 }
    407 /*}}}*/
    408 /*FUNCTION Tria::Enum {{{1*/
    409 int Tria::Enum(void){
    410 
    411         return TriaEnum;
    412 
    413 }
    414 /*}}}*/
    415 /*FUNCTION Tria::copy {{{1*/
    416 Object* Tria::copy() {
    417 
    418         int i;
    419         Tria* tria=NULL;
    420 
    421         tria=new Tria();
    422 
    423         /*copy fields: */
    424         tria->id=this->id;
    425         tria->interpolation_type=this->interpolation_type;
    426         if(this->inputs){
    427                 tria->inputs=(Inputs*)this->inputs->Copy();
    428         }
    429         else{
    430                 tria->inputs=new Inputs();
    431         }
    432         if(this->results){
    433                 tria->results=(Results*)this->results->Copy();
    434         }
    435         else{
    436                 tria->results=new Results();
    437         }
    438         /*point parameters: */
    439         tria->parameters=this->parameters;
    440 
    441         /*now deal with hooks and objects: */
    442         tria->InitHookNodes(this->numanalyses);
    443         for(i=0;i<this->numanalyses;i++)tria->hnodes[i].copy(&this->hnodes[i]);
    444         tria->hmatice.copy(&this->hmatice);
    445         tria->hmatpar.copy(&this->hmatpar);
    446 
    447         /*recover objects: */
    448         tria->nodes=(Node**)xmalloc(3*sizeof(Node*)); //we cannot rely on an analysis_counter to tell us which analysis_type we are running, so we just copy the nodes.
    449         for(i=0;i<3;i++)tria->nodes[i]=this->nodes[i];
    450         tria->matice=(Matice*)tria->hmatice.delivers();
    451         tria->matpar=(Matpar*)tria->hmatpar.delivers();
    452 
    453         return tria;
    454 }
    455 /*}}}*/
    456 
    457 /*Tria management: */
    458 /*FUNCTION Tria::Configure {{{1*/
    459 void  Tria::Configure(Elements* elementsin, Loads* loadsin, DataSet* nodesin, Materials* materialsin, Parameters* parametersin){
    460 
    461         int analysis_counter;
    462        
    463         /*go into parameters and get the analysis_counter: */
    464         parametersin->FindParam(&analysis_counter,AnalysisCounterEnum);
    465 
    466         /*Take care of hooking up all objects for this element, ie links the objects in the hooks to their respective
    467          * datasets, using internal ids and offsets hidden in hooks: */
    468         this->hnodes[analysis_counter].configure(nodesin);
    469         this->hmatice.configure(materialsin);
    470         this->hmatpar.configure(materialsin);
    471 
    472         /*Now, go pick up the objects inside the hooks: */
    473         this->nodes=(Node**)this->hnodes[analysis_counter].deliverp();
    474         this->matice=(Matice*)this->hmatice.delivers();
    475         this->matpar=(Matpar*)this->hmatpar.delivers();
    476 
    477         /*point parameters to real dataset: */
    478         this->parameters=parametersin;
    479 
    480 }
    481 /*}}}*/
    482 /*FUNCTION Tria::SpawnBeam {{{1*/
    483 void* Tria::SpawnBeam(int g0, int g1){
    484 
    485         int i;
    486 
    487         /*out of grids g0,g1 and g2 from Tria, build a beam element: */
    488         Beam* beam=NULL;
    489         int indices[2];
    490         int zero=0;
    491         Parameters *beam_parameters = NULL;
    492         Inputs     *beam_inputs     = NULL;
    493 
    494         indices[0]=g0;
    495         indices[1]=g1;
    496 
    497         beam_parameters=this->parameters;
    498         beam_inputs=(Inputs*)this->inputs->SpawnBeamInputs(indices);
    499 
    500         beam=new Beam();
    501         beam->id=this->id;
    502         beam->inputs=beam_inputs;
    503         beam->parameters=beam_parameters;
    504 
    505         /*now deal with nodes, matice and matpar: */
    506         beam->nodes=(Node**)xmalloc(2*sizeof(Node*));
    507         for(i=0;i<2;i++)beam->nodes[i]=this->nodes[indices[i]];
    508         beam->matice=this->matice;
    509         beam->matpar=this->matpar;
    510 
    511 
    512         return beam;
    513 }
    514 /*}}}*/
    515 /*FUNCTION Tria::SpawnSing {{{1*/
    516 void* Tria::SpawnSing(int index){
    517 
    518         Sing* sing=NULL;
    519         int zero=0;
    520         Parameters *sing_parameters = NULL;
    521         Inputs     *sing_inputs     = NULL;
    522 
    523         sing_parameters=this->parameters;
    524         sing_inputs=(Inputs*)this->inputs->SpawnSingInputs(index);
    525 
    526         sing=new Sing();
    527         sing->id=this->id;
    528         sing->inputs=sing_inputs;
    529         sing->parameters=sing_parameters;
    530 
    531         /*now deal with node,matice and matpar: */
    532         sing->node=this->nodes[index];
    533         sing->matice=this->matice;
    534         sing->matpar=this->matpar;
    535        
    536         return sing;
    537 }
    538 /*}}}*/
    539 /*FUNCTION Tria::InputToResult(int enum_type,int step,double time){{{1*/
    540 void  Tria::InputToResult(int enum_type,int step,double time){
    541 
    542         int    i;
    543         bool   found = false;
    544         Input *input = NULL;
    545 
    546         /*Go through all the input objects, and find the one corresponding to enum_type, if it exists: */
    547         for (i=0;i<this->inputs->Size();i++){
    548                 input=(Input*)this->inputs->GetObjectByOffset(i);
    549                 if (input->EnumType()==enum_type){
    550                         found=true;
    551                         break;
    552                 }
    553         }
    554 
    555         /*If we don't find it, no big deal, just don't do the transfer. Otherwise, build a new Result
    556          * object out of the input, with the additional step and time information: */
    557         this->results->AddObject((Object*)input->SpawnResult(step,time));
    558 
    559 }
    560 /*}}}*/
    561 /*FUNCTION Tria::ProcessResultsUnits(void){{{1*/
    562 void  Tria::ProcessResultsUnits(void){
    563 
    564         int i;
    565 
    566         for(i=0;i<this->results->Size();i++){
    567                 ElementResult* elementresult=(ElementResult*)this->results->GetObjectByOffset(i);
    568                 elementresult->ProcessUnits(this->parameters);
    569         }
    570 
    571 }
    572 /*}}}*/
    573 
    574 /*Updates: */
    575 /*FUNCTION Tria::UpdateGeometry{{{1*/
    576 void  Tria::UpdateGeometry(void){
    577 
    578         /*Intermediaries*/
    579         double rho_ice,rho_water;
    580 
    581         /*If shelf: hydrostatic equilibrium*/
    582         if (this->GetShelf()){
    583 
    584                 /*recover material parameters: */
    585                 rho_ice=matpar->GetRhoIce();
    586                 rho_water=matpar->GetRhoWater();
    587 
    588                 /*Create New Surface: s = (1-rho_ice/rho_water) h*/
    589                 InputDuplicate(ThicknessEnum,SurfaceEnum);     //1: copy thickness into surface
    590                 InputScale(SurfaceEnum,(1-rho_ice/rho_water)); //2: surface = surface * (1-di)
    591 
    592                 /*Create New Bed b = -rho_ice/rho_water h*/
    593                 InputDuplicate(ThicknessEnum,BedEnum);         //1: copy thickness into bed
    594                 InputScale(BedEnum, -rho_ice/rho_water);       //2: bed = bed * (-di)
    595         }
    596 
    597         /*If sheet: surface = bed + thickness*/
    598         else{
    599 
    600                 /*The bed does not change, update surface only s = b + h*/
    601                 InputDuplicate(BedEnum,SurfaceEnum);          //1: copy bed into surface
    602                 InputAXPY(SurfaceEnum,1.0,ThicknessEnum);     //2: surface = surface + 1 * thickness
    603         }
    604 
    605 }
    606 /*}}}*/
    607 /*FUNCTION Tria::UpdateFromDakota {{{1*/
    608 void  Tria::UpdateFromDakota(void* vinputs){
    609 
    610         int     i;
    611         int     dofs[1]={0};
    612         double  temperature_list[3];
    613         double  temperature_average;
    614         double  B_list[3];
    615         double  B_average;
    616         double  new_h[3];
    617 
    618         /*Update internal data if inputs holds new values: */
    619         /*inputs->Recover("thickness",&this->properties.h[0],1,dofs,3,(void**)nodes);
    620         if(inputs->Recover("thickness",&new_h[0],1,dofs,3,(void**)nodes)){
    621         //density, needed later:
    622         double di=(this->matpar->GetRhoIce()/this->matpar->GetRhoWater());
    623         //Go through grids:
    624         for (i=0;i<3;i++){
    625         if(nodes[i]->IsOnShelf()){
    626         this->b[i]=this->b[i]-di*(new_h[i]-h[i]); //hydrostatic equilibrium;
    627         }
    628         this->s[i]=this->b[i]+new_h[i];
    629         this->h[i]=new_h[i];
    630         }
    631         }*/
    632 
    633         ISSMERROR("not supported yet!");
    634 
     295/*FUNCTION Tria::MyRank {{{1*/
     296int    Tria::MyRank(void){
     297        extern int my_rank;
     298        return my_rank;
     299}
     300/*}}}*/
     301
     302/*Update virtual functions definitions: */
     303/*FUNCTION Tria::InputUpdateFromConstant(int value, int name);{{{1*/
     304void  Tria::InputUpdateFromConstant(int constant, int name){
     305        /*Nothing updated for now*/
     306}
     307/*}}}*/
     308/*FUNCTION Tria::InputUpdateFromConstant(double value, int name);{{{1*/
     309void  Tria::InputUpdateFromConstant(double constant, int name){
     310        /*Nothing updated for now*/
     311}
     312/*}}}*/
     313/*FUNCTION Tria::InputUpdateFromConstant(bool value, int name);{{{1*/
     314void  Tria::InputUpdateFromConstant(bool constant, int name){
     315        /*Nothing updated for now*/
    635316}
    636317/*}}}*/
     
    650331                InputUpdateFromSolutionDiagnosticHoriz( solution);
    651332        }
    652         else if (analysis_type==SlopeAnalysisEnum){
     333        else if (analysis_type==BedSlopeAnalysisEnum || analysis_type==SurfaceSlopeAnalysisEnum){
    653334                InputUpdateFromSolutionSlopeCompute( solution);
    654335        }
     
    673354}
    674355/*}}}*/
    675 /*FUNCTION Tria::InputUpdateFromSolutionDiagnosticHoriz {{{1*/
    676 void  Tria::InputUpdateFromSolutionDiagnosticHoriz(double* solution){
    677        
    678         int i;
    679 
    680         const int    numvertices=3;
    681         const int    numdofpervertex=2;
    682         const int    numdof=numdofpervertex*numvertices;
    683        
    684         int          doflist[numdof];
    685         double       values[numdof];
    686         double       vx[numvertices];
    687         double       vy[numvertices];
    688         double       vz[numvertices];
    689         double       vel[numvertices];
    690         double       pressure[numvertices];
    691         double       thickness[numvertices];
    692         double       rho_ice,g;
    693         double       gauss[numvertices][numvertices]={{1,0,0},{0,1,0},{0,0,1}};
    694 
    695         int          dummy;
    696         Input*       VzInput=NULL;
    697         double*      VzPtr=NULL;
    698        
    699         /*Get dof list: */
    700         GetDofList(&doflist[0],&dummy);
    701 
    702         /*Use the dof list to index into the solution vector: */
    703         for(i=0;i<numdof;i++){
    704                 values[i]=solution[doflist[i]];
    705         }
    706 
    707         /*Ok, we have vx and vy in values, fill in vx and vy arrays: */
    708         for(i=0;i<numvertices;i++){
    709                 vx[i]=values[i*numdofpervertex+0];
    710                 vy[i]=values[i*numdofpervertex+1];
    711         }
    712 
    713         /*Get Vz*/
    714         VzInput=inputs->GetInput(VzEnum);
    715         if (VzInput){
    716                 if (VzInput->Enum()!=TriaVertexInputEnum){
    717                         ISSMERROR("Cannot compute Vel as Vz is of type %s",EnumAsString(VzInput->Enum()));
    718                 }
    719                 VzInput->GetValuesPtr(&VzPtr,&dummy);
    720                 for(i=0;i<numvertices;i++) vz[i]=VzPtr[i];
    721         }
    722         else{
    723                 for(i=0;i<numvertices;i++) vz[i]=0.0;
    724         }
    725 
    726         /*Now Compute vel*/
    727         for(i=0;i<numvertices;i++) vel[i]=pow( pow(vx[i],2.0) + pow(vy[i],2.0) + pow(vz[i],2.0) , 0.5);
    728 
    729         /*For pressure: we have not computed pressure in this analysis, for this element. We are in 2D,
    730          *so the pressure is just the pressure at the bedrock: */
    731         rho_ice=matpar->GetRhoIce();
    732         g=matpar->GetG();
    733         inputs->GetParameterValues(&thickness[0],&gauss[0][0],3,ThicknessEnum);
    734        
    735         for(i=0;i<numvertices;i++){
    736                 pressure[i]=rho_ice*g*thickness[i];
    737         }
    738 
    739         /*Now, we have to move the previous Vx and Vy inputs  to old
    740          * status, otherwise, we'll wipe them off: */
    741         this->inputs->ChangeEnum(VxEnum,VxOldEnum);
    742         this->inputs->ChangeEnum(VyEnum,VyOldEnum);
    743         this->inputs->ChangeEnum(PressureEnum,PressureOldEnum);
    744 
    745         /*Add vx and vy as inputs to the tria element: */
    746         this->inputs->AddInput(new TriaVertexInput(VxEnum,vx));
    747         this->inputs->AddInput(new TriaVertexInput(VyEnum,vy));
    748         this->inputs->AddInput(new TriaVertexInput(VelEnum,vel));
    749         this->inputs->AddInput(new TriaVertexInput(PressureEnum,pressure));
    750 
    751 }
    752 
    753 /*}}}*/
    754 /*FUNCTION Tria::InputUpdateFromSolutionSlopeCompute {{{1*/
    755 void  Tria::InputUpdateFromSolutionSlopeCompute(double* solution){
     356/*FUNCTION Tria::InputUpdateFromVector(double* vector, int name, int type);{{{1*/
     357void  Tria::InputUpdateFromVector(double* vector, int name, int type){
     358
     359        /*Check that name is an element input*/
     360        if (!IsInput(name)) return;
     361
     362        switch(type){
     363
     364                case VertexEnum:
     365
     366                        /*New PentaVertexInpu*/
     367                        double values[3];
     368
     369                        /*Get values on the 6 vertices*/
     370                        for (int i=0;i<3;i++){
     371                                values[i]=vector[this->nodes[i]->GetVertexDof()];
     372                        }
     373
     374                        /*update input*/
     375                        this->inputs->AddInput(new TriaVertexInput(name,values));
     376                        return;
     377
     378                default:
     379
     380                        ISSMERROR("type %i (%s) not implemented yet",type,EnumAsString(type));
     381        }
     382}
     383/*}}}*/
     384/*FUNCTION Tria::InputUpdateFromVector(int* vector, int name, int type);{{{1*/
     385void  Tria::InputUpdateFromVector(int* vector, int name, int type){
    756386        ISSMERROR(" not supported yet!");
    757387}
    758388/*}}}*/
    759 /*FUNCTION Tria::InputUpdateFromSolutionPrognostic {{{1*/
    760 void  Tria::InputUpdateFromSolutionPrognostic(double* solution){
    761 
    762         int i;
    763 
    764         const int    numvertices=3;
    765         const int    numdofpervertex=1;
    766         const int    numdof=numdofpervertex*numvertices;
    767 
    768         int          doflist[numdof];
    769         double       values[numdof];
    770         double       thickness[numvertices];
    771 
    772         int          dummy;
    773 
    774         /*Get dof list: */
    775         GetDofList(&doflist[0],&dummy);
    776 
    777         /*Use the dof list to index into the solution vector: */
    778         for(i=0;i<numdof;i++){
    779                 values[i]=solution[doflist[i]];
    780         }
    781 
    782         /*Add thickness as inputs to the tria element: */
    783         this->inputs->AddInput(new TriaVertexInput(ThicknessEnum,values));
    784 }
    785 /*}}}*/
    786 /*FUNCTION Tria::InputUpdateFromSolutionPrognostic2 {{{1*/
    787 void  Tria::InputUpdateFromSolutionPrognostic2(double* solution){
     389/*FUNCTION Tria::InputUpdateFromVector(bool* vector, int name, int type);{{{1*/
     390void  Tria::InputUpdateFromVector(bool* vector, int name, int type){
    788391        ISSMERROR(" not supported yet!");
    789392}
    790393/*}}}*/
    791 /*FUNCTION Tria::InputUpdateFromSolutionBalancedthickness {{{1*/
    792 void  Tria::InputUpdateFromSolutionBalancedthickness(double* solution){
    793 
    794         int i;
    795 
    796         const int    numvertices=3;
    797         const int    numdofpervertex=1;
    798         const int    numdof=numdofpervertex*numvertices;
    799 
    800         int          doflist[numdof];
    801         double       values[numdof];
    802         double       thickness[numvertices];
    803 
    804         int          dummy;
    805 
    806         /*Get dof list: */
    807         GetDofList(&doflist[0],&dummy);
    808 
    809         /*Use the dof list to index into the solution vector: */
    810         for(i=0;i<numdof;i++){
    811                 values[i]=solution[doflist[i]];
    812         }
    813 
    814         /*Add thickness as inputs to the tria element: */
    815         this->inputs->AddInput(new TriaVertexInput(ThicknessEnum,values));
    816 }
    817 /*}}}*/
    818 /*FUNCTION Tria::InputUpdateFromSolutionBalancedthickness2 {{{1*/
    819 void  Tria::InputUpdateFromSolutionBalancedthickness2(double* solution){
    820         ISSMERROR(" not supported yet!");
    821 }
    822 /*}}}*/
    823 /*FUNCTION Tria::InputUpdateFromSolutionBalancedvelocities {{{1*/
    824 void  Tria::InputUpdateFromSolutionBalancedvelocities(double* solution){
    825         ISSMERROR(" not supported yet!");
    826 }
    827 /*}}}*/
    828 /*FUNCTION Tria::GetSolutionFromInputs(Vec solution){{{1*/
    829 void  Tria::GetSolutionFromInputs(Vec solution){
    830 
    831         int analysis_type;
    832 
    833         /*retrive parameters: */
    834         parameters->FindParam(&analysis_type,AnalysisTypeEnum);
    835        
    836         /*Just branch to the correct InputUpdateFromSolution generator, according to the type of analysis we are carrying out: */
    837         if (analysis_type==DiagnosticHorizAnalysisEnum)
    838                 GetSolutionFromInputsDiagnosticHoriz(solution);
    839         else
    840          ISSMERROR("%s%i%s\n","analysis: ",analysis_type," not supported yet");
    841 
    842 }
    843 /*}}}*/
    844 /*FUNCTION Tria::GetSolutionFromInputsDiagnosticHoriz(Vec solution){{{1*/
    845 void  Tria::GetSolutionFromInputsDiagnosticHoriz(Vec solution){
    846 
    847         int i;
    848 
    849         const int    numvertices=3;
    850         const int    numdofpervertex=2;
    851         const int    numdof=numdofpervertex*numvertices;
    852         double       gauss[numvertices][numvertices]={{1,0,0},{0,1,0},{0,0,1}};
    853 
    854         int          doflist[numdof];
    855         double       values[numdof];
    856         double       vx;
    857         double       vy;
    858 
    859         int          dummy;
    860 
    861         /*Get dof list: */
    862         GetDofList(&doflist[0],&dummy);
    863 
    864         /*Ok, we have vx and vy in values, fill in vx and vy arrays: */
    865         /*P1 element only for now*/
    866         for(i=0;i<numvertices;i++){
    867 
    868                 /*Recover vx and vy*/
    869                 inputs->GetParameterValue(&vx,&gauss[i][0],VxEnum);
    870                 inputs->GetParameterValue(&vy,&gauss[i][0],VyEnum);
    871                 values[i*numdofpervertex+0]=vx;
    872                 values[i*numdofpervertex+1]=vy;
    873         }
    874 
    875         /*Add value to global vector*/
    876         VecSetValues(solution,numdof,doflist,(const double*)values,INSERT_VALUES);
    877 
    878 }
    879 /*}}}*/
    880 
    881 /*Object functions*/
    882 /*FUNCTION Tria::IsInput{{{1*/
    883 bool Tria::IsInput(int name){
    884         if (name==SurfaceSlopeXEnum ||
    885                                 name==SurfaceSlopeYEnum){
    886                 return true;
    887         }
    888         else return false;
    889 }
    890 /*}}}*/
     394
     395/*Element virtual functions definitions: */
    891396/*FUNCTION Tria::ComputeBasalStress {{{1*/
    892397void  Tria::ComputeBasalStress(Vec eps){
     
    947452}
    948453/*}}}*/
     454/*FUNCTION Tria::Configure {{{1*/
     455void  Tria::Configure(Elements* elementsin, Loads* loadsin, DataSet* nodesin, Materials* materialsin, Parameters* parametersin){
     456
     457        int analysis_counter;
     458       
     459        /*go into parameters and get the analysis_counter: */
     460        parametersin->FindParam(&analysis_counter,AnalysisCounterEnum);
     461
     462        /*Take care of hooking up all objects for this element, ie links the objects in the hooks to their respective
     463         * datasets, using internal ids and offsets hidden in hooks: */
     464        this->hnodes[analysis_counter].configure(nodesin);
     465        this->hmatice.configure(materialsin);
     466        this->hmatpar.configure(materialsin);
     467
     468        /*Now, go pick up the objects inside the hooks: */
     469        this->nodes=(Node**)this->hnodes[analysis_counter].deliverp();
     470        this->matice=(Matice*)this->hmatice.delivers();
     471        this->matpar=(Matpar*)this->hmatpar.delivers();
     472
     473        /*point parameters to real dataset: */
     474        this->parameters=parametersin;
     475
     476}
     477/*}}}*/
    949478/*FUNCTION Tria::CostFunction {{{1*/
    950479double Tria::CostFunction(void){
     
    1070599                CreateKMatrixDiagnosticHutter( Kgg);
    1071600        }
    1072         else if (analysis_type==SlopeAnalysisEnum){
     601        else if (analysis_type==BedSlopeAnalysisEnum || analysis_type==SurfaceSlopeAnalysisEnum){
    1073602                CreateKMatrixSlopeCompute( Kgg);
    1074603        }
     
    1091620                ISSMERROR("analysis %i (%s) not supported yet",analysis_type,EnumAsString(analysis_type));
    1092621        }
    1093 
    1094 }
    1095 /*}}}*/
    1096 /*FUNCTION Tria::CreateKMatrixBalancedthickness {{{1*/
    1097 void  Tria::CreateKMatrixBalancedthickness(Mat Kgg){
    1098 
    1099         /* local declarations */
    1100         int             i,j;
    1101 
    1102         /* node data: */
    1103         const int    numgrids=3;
    1104         const int    NDOF1=1;
    1105         const int    numdof=NDOF1*numgrids;
    1106         double       xyz_list[numgrids][3];
    1107         int          doflist[numdof];
    1108         int          numberofdofspernode;
    1109 
    1110         /* gaussian points: */
    1111         int     num_gauss,ig;
    1112         double* first_gauss_area_coord  =  NULL;
    1113         double* second_gauss_area_coord =  NULL;
    1114         double* third_gauss_area_coord  =  NULL;
    1115         double* gauss_weights           =  NULL;
    1116         double  gauss_weight;
    1117         double  gauss_l1l2l3[3];
    1118 
    1119         /* matrices: */
    1120         double L[numgrids];
    1121         double B[2][numgrids];
    1122         double Bprime[2][numgrids];
    1123         double DL[2][2]={0.0};
    1124         double DLprime[2][2]={0.0};
    1125         double DL_scalar;
    1126         double Ke_gg[numdof][numdof]={0.0};//local element stiffness matrix
    1127         double Ke_gg_gaussian[numdof][numdof]={0.0}; //stiffness matrix evaluated at the gaussian point.
    1128         double Ke_gg_thickness1[numdof][numdof]={0.0}; //stiffness matrix evaluated at the gaussian point.
    1129         double Ke_gg_thickness2[numdof][numdof]={0.0}; //stiffness matrix evaluated at the gaussian point.
    1130 
    1131         double Jdettria;
    1132 
    1133         /*input parameters for structural analysis (diagnostic): */
    1134         double  dvx[2];
    1135         double  dvy[2];
    1136         double  vx,vy;
    1137         double  dvxdx,dvydy;
    1138         double  v_gauss[2]={0.0};
    1139 
    1140 
    1141         double  K[2][2]={0.0};
    1142         double  KDL[2][2]={0.0};
    1143         int     dofs[2]={0,1};
    1144         int     found=0;
    1145 
    1146         /*parameters: */
    1147         bool artdiff;
    1148 
    1149         /* Get node coordinates and dof list: */
    1150         GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
    1151         GetDofList(&doflist[0],&numberofdofspernode);
    1152 
    1153         /*retrieve some parameters: */
    1154         this->parameters->FindParam(&artdiff,ArtDiffEnum);
    1155 
    1156         //Create Artificial diffusivity once for all if requested
    1157         if(artdiff){
    1158                 //Get the Jacobian determinant
    1159                 gauss_l1l2l3[0]=ONETHIRD; gauss_l1l2l3[1]=ONETHIRD; gauss_l1l2l3[2]=ONETHIRD;
    1160                 GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss_l1l2l3);
    1161 
    1162                 //Build K matrix (artificial diffusivity matrix)
    1163                 inputs->GetParameterAverage(&v_gauss[0],VxAverageEnum);
    1164                 inputs->GetParameterAverage(&v_gauss[1],VyAverageEnum);
    1165 
    1166                 K[0][0]=pow(Jdettria,(double).5)/2.0*fabs(v_gauss[0]);
    1167                 K[1][1]=pow(Jdettria,(double).5)/2.0*fabs(v_gauss[1]);
    1168         }
    1169 
    1170         /* Get gaussian points and weights (make this a statically initialized list of points? fstd): */
    1171         GaussTria( &num_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &gauss_weights, 2);
    1172 
    1173         /* Start  looping on the number of gaussian points: */
    1174         for (ig=0; ig<num_gauss; ig++){
    1175                 /*Pick up the gaussian point: */
    1176                 gauss_weight=*(gauss_weights+ig);
    1177                 gauss_l1l2l3[0]=*(first_gauss_area_coord+ig);
    1178                 gauss_l1l2l3[1]=*(second_gauss_area_coord+ig);
    1179                 gauss_l1l2l3[2]=*(third_gauss_area_coord+ig);
    1180 
    1181                 /* Get Jacobian determinant: */
    1182                 GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss_l1l2l3);
    1183 
    1184                 /*Get B  and B prime matrix: */
    1185                 GetB_prog(&B[0][0], &xyz_list[0][0], gauss_l1l2l3);
    1186                 GetBPrime_prog(&Bprime[0][0], &xyz_list[0][0], gauss_l1l2l3);
    1187 
    1188                 //Get vx, vy and their derivatives at gauss point
    1189                 inputs->GetParameterValue(&vx, &gauss_l1l2l3[0],VxAverageEnum);
    1190                 inputs->GetParameterValue(&vy, &gauss_l1l2l3[0],VyAverageEnum);
    1191 
    1192                 inputs->GetParameterDerivativeValue(&dvx[0],&xyz_list[0][0],&gauss_l1l2l3[0],VxAverageEnum);
    1193                 inputs->GetParameterDerivativeValue(&dvy[0],&xyz_list[0][0],&gauss_l1l2l3[0],VyAverageEnum);
    1194 
    1195                 dvxdx=dvx[0];
    1196                 dvydy=dvy[1];
    1197 
    1198                 DL_scalar=gauss_weight*Jdettria;
    1199 
    1200                 //Create DL and DLprime matrix
    1201                 DL[0][0]=DL_scalar*dvxdx;
    1202                 DL[1][1]=DL_scalar*dvydy;
    1203 
    1204                 DLprime[0][0]=DL_scalar*vx;
    1205                 DLprime[1][1]=DL_scalar*vy;
    1206 
    1207                 //Do the triple product tL*D*L.
    1208                 //Ke_gg_thickness=B'*DLprime*Bprime;
    1209 
    1210                 TripleMultiply( &B[0][0],2,numdof,1,
    1211                                         &DL[0][0],2,2,0,
    1212                                         &B[0][0],2,numdof,0,
    1213                                         &Ke_gg_thickness1[0][0],0);
    1214 
    1215                 TripleMultiply( &B[0][0],2,numdof,1,
    1216                                         &DLprime[0][0],2,2,0,
    1217                                         &Bprime[0][0],2,numdof,0,
    1218                                         &Ke_gg_thickness2[0][0],0);
    1219 
    1220                 /* Add the Ke_gg_gaussian, and optionally Ke_gg_drag_gaussian onto Ke_gg: */
    1221                 for( i=0; i<numdof; i++) for(j=0;j<numdof;j++) Ke_gg[i][j]+=Ke_gg_thickness1[i][j];
    1222                 for( i=0; i<numdof; i++) for(j=0;j<numdof;j++) Ke_gg[i][j]+=Ke_gg_thickness2[i][j];
    1223 
    1224                 if(artdiff){
    1225 
    1226                         /* Compute artificial diffusivity */
    1227                         KDL[0][0]=DL_scalar*K[0][0];
    1228                         KDL[1][1]=DL_scalar*K[1][1];
    1229 
    1230                         TripleMultiply( &Bprime[0][0],2,numdof,1,
    1231                                                 &KDL[0][0],2,2,0,
    1232                                                 &Bprime[0][0],2,numdof,0,
    1233                                                 &Ke_gg_gaussian[0][0],0);
    1234 
    1235                         /* Add artificial diffusivity matrix */
    1236                         for( i=0; i<numdof; i++) for(j=0;j<numdof;j++) Ke_gg[i][j]+=Ke_gg_gaussian[i][j];
    1237 
    1238                 }
    1239         } // for (ig=0; ig<num_gauss; ig++)
    1240 
    1241         /*Add Ke_gg to global matrix Kgg: */
    1242         MatSetValues(Kgg,numdof,doflist,numdof,doflist,(const double*)Ke_gg,ADD_VALUES);
    1243 
    1244 cleanup_and_return:
    1245         xfree((void**)&first_gauss_area_coord);
    1246         xfree((void**)&second_gauss_area_coord);
    1247         xfree((void**)&third_gauss_area_coord);
    1248         xfree((void**)&gauss_weights);
    1249 
    1250 }
    1251 /*}}}*/
    1252 /*FUNCTION Tria::CreateKMatrixBalancedthickness2 {{{1*/
    1253 void  Tria::CreateKMatrixBalancedthickness2(Mat Kgg){
    1254 
    1255         /* local declarations */
    1256         int             i,j;
    1257 
    1258         /* node data: */
    1259         const int    numgrids=3;
    1260         const int    NDOF1=1;
    1261         const int    numdof=NDOF1*numgrids;
    1262         double       xyz_list[numgrids][3];
    1263         int          doflist[numdof];
    1264         int          numberofdofspernode;
    1265 
    1266         /* gaussian points: */
    1267         int     num_gauss,ig;
    1268         double* first_gauss_area_coord  =  NULL;
    1269         double* second_gauss_area_coord =  NULL;
    1270         double* third_gauss_area_coord  =  NULL;
    1271         double* gauss_weights           =  NULL;
    1272         double  gauss_weight;
    1273         double  gauss_l1l2l3[3];
    1274 
    1275         /* matrices: */
    1276         double B[2][numgrids];
    1277         double Bprime[2][numgrids];
    1278         double DL[2][2]={0.0};
    1279         double DLprime[2][2]={0.0};
    1280         double DL_scalar;
    1281         double Ke_gg[numdof][numdof]={0.0};
    1282         double Ke_gg2[numdof][numdof]={0.0};
    1283         double Jdettria;
    1284 
    1285         /*input parameters for structural analysis (diagnostic): */
    1286         double  vx,vy;
    1287         int     dofs[1]={0};
    1288         int     found;
    1289 
    1290         /* Get node coordinates and dof list: */
    1291         GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
    1292         GetDofList(&doflist[0],&numberofdofspernode);
    1293 
    1294         /* Get gaussian points and weights (make this a statically initialized list of points? fstd): */
    1295         GaussTria( &num_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &gauss_weights, 2);
    1296 
    1297         /* Start  looping on the number of gaussian points: */
    1298         for (ig=0; ig<num_gauss; ig++){
    1299                 /*Pick up the gaussian point: */
    1300                 gauss_weight=*(gauss_weights+ig);
    1301                 gauss_l1l2l3[0]=*(first_gauss_area_coord+ig);
    1302                 gauss_l1l2l3[1]=*(second_gauss_area_coord+ig);
    1303                 gauss_l1l2l3[2]=*(third_gauss_area_coord+ig);
    1304 
    1305                 /* Get Jacobian determinant: */
    1306                 GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss_l1l2l3);
    1307 
    1308                 /*Get B  and B prime matrix: */
    1309                 /*WARNING: B and Bprime are inverted compared to usual prognostic!!!!*/
    1310                 GetB_prog(&Bprime[0][0], &xyz_list[0][0], gauss_l1l2l3);
    1311                 GetBPrime_prog(&B[0][0], &xyz_list[0][0], gauss_l1l2l3);
    1312 
    1313                 //Get vx, vy and their derivatives at gauss point
    1314                 inputs->GetParameterValue(&vx, &gauss_l1l2l3[0],VxEnum);
    1315                 inputs->GetParameterValue(&vy, &gauss_l1l2l3[0],VyEnum);
    1316 
    1317                 DL_scalar=-gauss_weight*Jdettria;
    1318 
    1319                 DLprime[0][0]=DL_scalar*vx;
    1320                 DLprime[1][1]=DL_scalar*vy;
    1321 
    1322                 //Do the triple product tL*D*L.
    1323                 TripleMultiply( &B[0][0],2,numdof,1,
    1324                                         &DLprime[0][0],2,2,0,
    1325                                         &Bprime[0][0],2,numdof,0,
    1326                                         &Ke_gg2[0][0],0);
    1327 
    1328                 /* Add the Ke_gg_gaussian, and optionally Ke_gg_drag_gaussian onto Ke_gg: */
    1329                 for( i=0; i<numdof; i++) for(j=0;j<numdof;j++) Ke_gg[i][j]+=Ke_gg2[i][j];
    1330 
    1331         } // for (ig=0; ig<num_gauss; ig++)
    1332 
    1333         /*Add Ke_gg to global matrix Kgg: */
    1334         MatSetValues(Kgg,numdof,doflist,numdof,doflist,(const double*)Ke_gg,ADD_VALUES);
    1335 
    1336 cleanup_and_return:
    1337         xfree((void**)&first_gauss_area_coord);
    1338         xfree((void**)&second_gauss_area_coord);
    1339         xfree((void**)&third_gauss_area_coord);
    1340         xfree((void**)&gauss_weights);
    1341 
    1342 }
    1343 /*}}}*/
    1344 /*FUNCTION Tria::CreateKMatrixBalancedvelocities {{{1*/
    1345 void  Tria::CreateKMatrixBalancedvelocities(Mat Kgg){
    1346 
    1347         /* local declarations */
    1348         int             i,j;
    1349 
    1350         /* node data: */
    1351         const int    numgrids=3;
    1352         const int    NDOF1=1;
    1353         const int    numdof=NDOF1*numgrids;
    1354         double       xyz_list[numgrids][3];
    1355         int          doflist[numdof];
    1356         int          numberofdofspernode;
    1357         double  gaussgrids[numgrids][numgrids]={{1,0,0},{0,1,0},{0,0,1}};
    1358 
    1359         /* gaussian points: */
    1360         int     num_gauss,ig;
    1361         double* first_gauss_area_coord  =  NULL;
    1362         double* second_gauss_area_coord =  NULL;
    1363         double* third_gauss_area_coord  =  NULL;
    1364         double* gauss_weights           =  NULL;
    1365         double  gauss_weight;
    1366         double  gauss_l1l2l3[3];
    1367 
    1368         /* matrices: */
    1369         double L[numgrids];
    1370         double B[2][numgrids];
    1371         double Bprime[2][numgrids];
    1372         double DL[2][2]={0.0};
    1373         double DLprime[2][2]={0.0};
    1374         double DL_scalar;
    1375         double Ke_gg[numdof][numdof]={0.0};//local element stiffness matrix
    1376         double Ke_gg_gaussian[numdof][numdof]={0.0}; //stiffness matrix evaluated at the gaussian point.
    1377         double Ke_gg_velocities1[numdof][numdof]={0.0}; //stiffness matrix evaluated at the gaussian point.
    1378         double Ke_gg_velocities2[numdof][numdof]={0.0}; //stiffness matrix evaluated at the gaussian point.
    1379         double Jdettria;
    1380 
    1381         /*input parameters for structural analysis (diagnostic): */
    1382         double  surface_normal[3];
    1383         double  surface_list[3];
    1384         double  nx,ny,norm;
    1385         double  dvx[2];
    1386         double  dvy[2];
    1387         double  vx,vy;
    1388         double  dvxdx,dvydy;
    1389         double  v_gauss[2]={0.0};
    1390         double  K[2][2]={0.0};
    1391         double  KDL[2][2]={0.0};
    1392         int     dofs[2]={0,1};
    1393         int     found=0;
    1394 
    1395         /*parameters: */
    1396         bool artdiff;
    1397 
    1398         /*retrieve some parameters: */
    1399         this->parameters->FindParam(&artdiff,ArtDiffEnum);
    1400 
    1401         /* Get node coordinates and dof list: */
    1402         GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
    1403         GetDofList(&doflist[0],&numberofdofspernode);
    1404 
    1405         /*Modify z so that it reflects the surface*/
    1406         inputs->GetParameterValues(&surface_list[0],&gaussgrids[0][0],3,SurfaceEnum);
    1407         for(i=0;i<numgrids;i++) xyz_list[i][2]=surface_list[i];
    1408 
    1409         /*Get normal vector to the surface*/
    1410         inputs->GetParameterAverage(&nx,VxAverageEnum);
    1411         inputs->GetParameterAverage(&ny,VyAverageEnum);
    1412         if(nx==0 && ny==0){
    1413                 SurfaceNormal(&surface_normal[0],xyz_list);
    1414                 nx=surface_normal[0];
    1415                 ny=surface_normal[1];
    1416         }
    1417         if(nx==0 && ny==0){
    1418                 nx=0;
    1419                 ny=1;
    1420         }
    1421         norm=pow( pow(nx,2)+pow(ny,2) , (double).5);
    1422         nx=nx/norm;
    1423         ny=ny/norm;
    1424 
    1425         //Create Artificial diffusivity once for all if requested
    1426         if(artdiff){
    1427                 //Get the Jacobian determinant
    1428                 gauss_l1l2l3[0]=ONETHIRD; gauss_l1l2l3[1]=ONETHIRD; gauss_l1l2l3[2]=ONETHIRD;
    1429                 GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss_l1l2l3);
    1430 
    1431                 //Build K matrix (artificial diffusivity matrix)
    1432                 inputs->GetParameterAverage(&v_gauss[0],VxAverageEnum);
    1433                 inputs->GetParameterAverage(&v_gauss[1],VyAverageEnum);
    1434 
    1435                 K[0][0]=pow(10,2)*pow(Jdettria,(double).5)/2.0*fabs(v_gauss[0]); //pow should be zero!!
    1436                 K[1][1]=pow(10,2)*pow(Jdettria,(double).5)/2.0*fabs(v_gauss[1]);
    1437         }
    1438 
    1439         /* Get gaussian points and weights (make this a statically initialized list of points? fstd): */
    1440         GaussTria( &num_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &gauss_weights, 2);
    1441 
    1442         /* Start  looping on the number of gaussian points: */
    1443         for (ig=0; ig<num_gauss; ig++){
    1444                 /*Pick up the gaussian point: */
    1445                 gauss_weight=*(gauss_weights+ig);
    1446                 gauss_l1l2l3[0]=*(first_gauss_area_coord+ig);
    1447                 gauss_l1l2l3[1]=*(second_gauss_area_coord+ig);
    1448                 gauss_l1l2l3[2]=*(third_gauss_area_coord+ig);
    1449 
    1450                 /* Get Jacobian determinant: */
    1451                 GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss_l1l2l3);
    1452 
    1453                 /*Get B  and B prime matrix: */
    1454                 GetB_prog(&B[0][0], &xyz_list[0][0], gauss_l1l2l3);
    1455                 GetBPrime_prog(&Bprime[0][0], &xyz_list[0][0], gauss_l1l2l3);
    1456 
    1457                 //Get vx, vy and their derivatives at gauss point
    1458                 inputs->GetParameterValue(&vx,&gauss_l1l2l3[0],VxAverageEnum);
    1459                 inputs->GetParameterValue(&vy,&gauss_l1l2l3[0],VyAverageEnum);
    1460 
    1461                 inputs->GetParameterDerivativeValue(&dvx[0],&xyz_list[0][0],&gauss_l1l2l3[0],VxAverageEnum);
    1462                 inputs->GetParameterDerivativeValue(&dvy[0],&xyz_list[0][0],&gauss_l1l2l3[0],VyAverageEnum);
    1463 
    1464                 dvxdx=dvx[0];
    1465                 dvydy=dvy[1];
    1466 
    1467                 DL_scalar=gauss_weight*Jdettria;
    1468 
    1469                 DLprime[0][0]=DL_scalar*nx;
    1470                 DLprime[1][1]=DL_scalar*ny;
    1471 
    1472                 //Do the triple product tL*D*L.
    1473                 //Ke_gg_velocities=B'*DLprime*Bprime;
    1474                 TripleMultiply( &B[0][0],2,numdof,1,
    1475                                         &DLprime[0][0],2,2,0,
    1476                                         &Bprime[0][0],2,numdof,0,
    1477                                         &Ke_gg_velocities2[0][0],0);
    1478 
    1479                 /* Add the Ke_gg_gaussian, and optionally Ke_gg_drag_gaussian onto Ke_gg: */
    1480                 for( i=0; i<numdof; i++) for(j=0;j<numdof;j++) Ke_gg[i][j]+=Ke_gg_velocities2[i][j];
    1481 
    1482                 if(artdiff){
    1483 
    1484                         /* Compute artificial diffusivity */
    1485                         KDL[0][0]=DL_scalar*K[0][0];
    1486                         KDL[1][1]=DL_scalar*K[1][1];
    1487 
    1488                         TripleMultiply( &Bprime[0][0],2,numdof,1,
    1489                                                 &KDL[0][0],2,2,0,
    1490                                                 &Bprime[0][0],2,numdof,0,
    1491                                                 &Ke_gg_gaussian[0][0],0);
    1492 
    1493                         /* Add artificial diffusivity matrix */
    1494                         for( i=0; i<numdof; i++) for(j=0;j<numdof;j++) Ke_gg[i][j]+=Ke_gg_gaussian[i][j];
    1495 
    1496                 }
    1497 
    1498         } // for (ig=0; ig<num_gauss; ig++)
    1499 
    1500         /*Add Ke_gg to global matrix Kgg: */
    1501         MatSetValues(Kgg,numdof,doflist,numdof,doflist,(const double*)Ke_gg,ADD_VALUES);
    1502 
    1503 
    1504 cleanup_and_return:
    1505         xfree((void**)&first_gauss_area_coord);
    1506         xfree((void**)&second_gauss_area_coord);
    1507         xfree((void**)&third_gauss_area_coord);
    1508         xfree((void**)&gauss_weights);
    1509 
    1510 }
    1511 /*}}}*/
    1512 /*FUNCTION Tria::CreateKMatrixDiagnosticHoriz {{{1*/
    1513 void  Tria::CreateKMatrixDiagnosticHoriz(Mat Kgg){
    1514 
    1515         /* local declarations */
    1516         int             i,j;
    1517 
    1518         /* node data: */
    1519         const int    numgrids=3;
    1520         const int    numdof=2*numgrids;
    1521         double       xyz_list[numgrids][3];
    1522         int          doflist[numdof];
    1523         int          numberofdofspernode;
    1524 
    1525         /* gaussian points: */
    1526         int     num_gauss,ig;
    1527         double* first_gauss_area_coord  =  NULL;
    1528         double* second_gauss_area_coord =  NULL;
    1529         double* third_gauss_area_coord  =  NULL;
    1530         double* gauss_weights           =  NULL;
    1531         double  gauss_weight;
    1532         double  gauss_l1l2l3[3];
    1533 
    1534         /* material data: */
    1535         double viscosity; //viscosity
    1536         double newviscosity; //viscosity
    1537         double oldviscosity; //viscosity
    1538 
    1539         /* strain rate: */
    1540         double epsilon[3]; /* epsilon=[exx,eyy,exy];*/
    1541         double oldepsilon[3]; /* oldepsilon=[exx,eyy,exy];*/
    1542 
    1543         /* matrices: */
    1544         double B[3][numdof];
    1545         double Bprime[3][numdof];
    1546         double D[3][3]={0.0};  // material matrix, simple scalar matrix.
    1547         double D_scalar;
    1548 
    1549         /*parameters: */
    1550         double viscosity_overshoot;
    1551 
    1552         /* local element matrices: */
    1553         double Ke_gg[numdof][numdof]={0.0};
    1554         double Ke_gg_gaussian[numdof][numdof]; //stiffness matrix evaluated at the gaussian point.
    1555 
    1556         double Jdet;
    1557 
    1558         /*input parameters for structural analysis (diagnostic): */
    1559         double  thickness;
    1560         int     dofs[2]={0,1};
    1561 
    1562         /*inputs: */
    1563         bool onwater,shelf;
    1564 
    1565         /*retrieve inputs :*/
    1566         inputs->GetParameterValue(&onwater,ElementOnWaterEnum);
    1567         inputs->GetParameterValue(&shelf,ElementOnIceShelfEnum);
    1568 
    1569         /*retrieve some parameters: */
    1570         this->parameters->FindParam(&viscosity_overshoot,ViscosityOvershootEnum);
    1571 
    1572         /*First, if we are on water, return empty matrix: */
    1573         if(onwater) return;
    1574 
    1575         /* Get node coordinates and dof list: */
    1576         GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
    1577         GetDofList(&doflist[0],&numberofdofspernode);
    1578 
    1579         /* Get gaussian points and weights (make this a statically initialized list of points? fstd): */
    1580         GaussTria( &num_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &gauss_weights, 2);
    1581 
    1582         /* Start  looping on the number of gaussian points: */
    1583         for (ig=0; ig<num_gauss; ig++){
    1584                 /*Pick up the gaussian point: */
    1585                 gauss_weight=*(gauss_weights+ig);
    1586                 gauss_l1l2l3[0]=*(first_gauss_area_coord+ig);
    1587                 gauss_l1l2l3[1]=*(second_gauss_area_coord+ig);
    1588                 gauss_l1l2l3[2]=*(third_gauss_area_coord+ig);
    1589 
    1590 
    1591                 /*Compute thickness at gaussian point: */
    1592                 inputs->GetParameterValue(&thickness, gauss_l1l2l3,ThicknessEnum);
    1593 
    1594                 /*Get strain rate from velocity: */
    1595                 inputs->GetStrainRate2d(&epsilon[0],&xyz_list[0][0],gauss_l1l2l3,VxEnum,VyEnum);
    1596                 inputs->GetStrainRate2d(&oldepsilon[0],&xyz_list[0][0],gauss_l1l2l3,VxOldEnum,VyOldEnum);
    1597 
    1598                 /*Get viscosity: */
    1599                 matice->GetViscosity2d(&viscosity, &epsilon[0]);
    1600                 matice->GetViscosity2d(&oldviscosity, &oldepsilon[0]);
    1601 
    1602                 /* Get Jacobian determinant: */
    1603                 GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0],gauss_l1l2l3);
    1604 
    1605                 /* Build the D matrix: we plug the gaussian weight, the thickness, the viscosity, and the jacobian determinant
    1606                         onto this scalar matrix, so that we win some computational time: */
    1607                 newviscosity=viscosity+viscosity_overshoot*(viscosity-oldviscosity);
    1608                 D_scalar=newviscosity*thickness*gauss_weight*Jdet;
    1609 
    1610                 for (i=0;i<3;i++){
    1611                         D[i][i]=D_scalar;
    1612                 }
    1613 
    1614                 /*Get B and Bprime matrices: */
    1615                 GetB(&B[0][0], &xyz_list[0][0], gauss_l1l2l3);
    1616                 GetBPrime(&Bprime[0][0], &xyz_list[0][0], gauss_l1l2l3);
    1617 
    1618                 /*  Do the triple product tB*D*Bprime: */
    1619                 TripleMultiply( &B[0][0],3,numdof,1,
    1620                                         &D[0][0],3,3,0,
    1621                                         &Bprime[0][0],3,numdof,0,
    1622                                         &Ke_gg_gaussian[0][0],0);
    1623 
    1624                 /* Add the Ke_gg_gaussian, and optionally Ke_gg_drag_gaussian onto Ke_gg: */
    1625                 for( i=0; i<numdof; i++) for(j=0;j<numdof;j++) Ke_gg[i][j]+=Ke_gg_gaussian[i][j];
    1626 
    1627         } // for (ig=0; ig<num_gauss; ig++)
    1628 
    1629         /*Add Ke_gg to global matrix Kgg: */
    1630         MatSetValues(Kgg,numdof,doflist,numdof,doflist,(const double*)Ke_gg,ADD_VALUES);
    1631 
    1632         /*Do not forget to include friction: */
    1633         if(!shelf){
    1634                 CreateKMatrixDiagnosticHorizFriction(Kgg);
    1635         }
    1636 
    1637 cleanup_and_return:
    1638         xfree((void**)&first_gauss_area_coord);
    1639         xfree((void**)&second_gauss_area_coord);
    1640         xfree((void**)&third_gauss_area_coord);
    1641         xfree((void**)&gauss_weights);
    1642 
    1643 }
    1644 /*}}}*/
    1645 /*FUNCTION Tria::CreateKMatrixDiagnosticHorizFriction {{{1*/
    1646 void  Tria::CreateKMatrixDiagnosticHorizFriction(Mat Kgg){
    1647 
    1648 
    1649         /* local declarations */
    1650         int             i,j;
    1651         int analysis_type;
    1652 
    1653         /* node data: */
    1654         const int    numgrids=3;
    1655         const int    numdof=2*numgrids;
    1656         double       xyz_list[numgrids][3];
    1657         int          doflist[numdof];
    1658         int          numberofdofspernode;
    1659        
    1660         /* gaussian points: */
    1661         int     num_gauss,ig;
    1662         double* first_gauss_area_coord  =  NULL;
    1663         double* second_gauss_area_coord =  NULL;
    1664         double* third_gauss_area_coord  =  NULL;
    1665         double* gauss_weights           =  NULL;
    1666         double  gauss_weight;
    1667         double  gauss_l1l2l3[3];
    1668 
    1669         /* matrices: */
    1670         double L[2][numdof];
    1671         double DL[2][2]={{ 0,0 },{0,0}}; //for basal drag
    1672         double DL_scalar;
    1673 
    1674         /* local element matrices: */
    1675         double Ke_gg[numdof][numdof]={0.0};
    1676         double Ke_gg_gaussian[numdof][numdof]; //stiffness matrix contribution from drag
    1677        
    1678         double Jdet;
    1679        
    1680         /*slope: */
    1681         double  slope[2]={0.0,0.0};
    1682         double  slope_magnitude;
    1683 
    1684         /*friction: */
    1685         Friction* friction=NULL;
    1686         double alpha2;
    1687 
    1688         double MAXSLOPE=.06; // 6 %
    1689         double MOUNTAINKEXPONENT=10;
    1690 
    1691         /*inputs: */
    1692         bool shelf;
    1693         int  drag_type;
    1694 
    1695         /*retrive parameters: */
    1696         parameters->FindParam(&analysis_type,AnalysisTypeEnum);
    1697 
    1698         /*retrieve inputs :*/
    1699         inputs->GetParameterValue(&shelf,ElementOnIceShelfEnum);
    1700         inputs->GetParameterValue(&drag_type,DragTypeEnum);
    1701        
    1702         /* Get node coordinates and dof list: */
    1703         GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
    1704         GetDofList(&doflist[0],&numberofdofspernode);
    1705 
    1706         if (shelf){
    1707                 /*no friction, do nothing*/
    1708                 return;
    1709         }
    1710 
    1711         /*build friction object, used later on: */
    1712         if (drag_type!=2)ISSMERROR(" non-viscous friction not supported yet!");
    1713         friction=new Friction("2d",inputs,matpar,analysis_type);
    1714 
    1715         /* Get gaussian points and weights (make this a statically initialized list of points? fstd): */
    1716         GaussTria( &num_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &gauss_weights, 2);
    1717 
    1718         /* Start  looping on the number of gaussian points: */
    1719         for (ig=0; ig<num_gauss; ig++){
    1720                 /*Pick up the gaussian point: */
    1721                 gauss_weight=*(gauss_weights+ig);
    1722                 gauss_l1l2l3[0]=*(first_gauss_area_coord+ig);
    1723                 gauss_l1l2l3[1]=*(second_gauss_area_coord+ig);
    1724                 gauss_l1l2l3[2]=*(third_gauss_area_coord+ig);
    1725 
    1726                 /*Friction: */
    1727                 friction->GetAlpha2(&alpha2, gauss_l1l2l3,VxEnum,VyEnum,VzEnum);
    1728 
    1729                 // If we have a slope > 6% for this element,  it means  we are on a mountain. In this particular case,
    1730                 //velocity should be = 0. To achieve this result, we set alpha2_list to a very high value: */
    1731                 inputs->GetParameterDerivativeValue(&slope[0],&xyz_list[0][0],&gauss_l1l2l3[0],SurfaceEnum);
    1732                 slope_magnitude=sqrt(pow(slope[0],2)+pow(slope[1],2));
    1733 
    1734                 if (slope_magnitude>MAXSLOPE){
    1735                         alpha2=pow((double)10,MOUNTAINKEXPONENT);
    1736                 }
    1737 
    1738                 /* Get Jacobian determinant: */
    1739                 GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0],gauss_l1l2l3);
    1740 
    1741                 /*Get L matrix: */
    1742                 GetL(&L[0][0], &xyz_list[0][0], gauss_l1l2l3,numberofdofspernode);
    1743 
    1744                
    1745                 DL_scalar=alpha2*gauss_weight*Jdet;
    1746                 for (i=0;i<2;i++){
    1747                         DL[i][i]=DL_scalar;
    1748                 }
    1749                
    1750                 /*  Do the triple producte tL*D*L: */
    1751                 TripleMultiply( &L[0][0],2,numdof,1,
    1752                                         &DL[0][0],2,2,0,
    1753                                         &L[0][0],2,numdof,0,
    1754                                         &Ke_gg_gaussian[0][0],0);
    1755 
    1756                 for( i=0; i<numdof; i++) for(j=0;j<numdof;j++) Ke_gg[i][j]+=Ke_gg_gaussian[i][j];
    1757 
    1758         } // for (ig=0; ig<num_gauss; ig++)
    1759 
    1760         /*Add Ke_gg to global matrix Kgg: */
    1761         MatSetValues(Kgg,numdof,doflist,numdof,doflist,(const double*)Ke_gg,ADD_VALUES);
    1762 
    1763         cleanup_and_return:
    1764         xfree((void**)&first_gauss_area_coord);
    1765         xfree((void**)&second_gauss_area_coord);
    1766         xfree((void**)&third_gauss_area_coord);
    1767         xfree((void**)&gauss_weights);
    1768         delete friction;
    1769 
    1770 }       
    1771 /*}}}*/
    1772 /*FUNCTION Tria::CreateKMatrixDiagnosticHutter{{{1*/
    1773 void  Tria::CreateKMatrixDiagnosticHutter(Mat Kgg){
    1774 
    1775         /*Collapsed formulation: */
    1776         Sing*  sing=NULL;
    1777         int    i;
    1778 
    1779         /*flags: */
    1780         bool onwater;
    1781 
    1782         /*recover some inputs: */
    1783         inputs->GetParameterValue(&onwater,ElementOnWaterEnum);
    1784 
    1785         /*If on water, skip: */
    1786         if(onwater)return;
    1787 
    1788         /*Spawn 3 sing elements: */
    1789         for(i=0;i<3;i++){
    1790                 sing=(Sing*)SpawnSing(i);
    1791                 sing->CreateKMatrix(Kgg);
    1792         }
    1793 
    1794         /*clean up*/
    1795         delete sing;
    1796 
    1797 }
    1798 /*}}}*/
    1799 /*FUNCTION Tria::CreateKMatrixDiagnosticSurfaceVert {{{1*/
    1800 void  Tria::CreateKMatrixDiagnosticSurfaceVert(Mat Kgg){
    1801 
    1802         int i,j;
    1803 
    1804         /* node data: */
    1805         const int    numgrids=3;
    1806         const int    NDOF1=1;
    1807         const int    numdof=NDOF1*numgrids;
    1808         double       xyz_list[numgrids][3];
    1809         int          doflist[numdof];
    1810         int          numberofdofspernode;
    1811 
    1812         /* gaussian points: */
    1813         int     num_gauss,ig;
    1814         double* first_gauss_area_coord  =  NULL;
    1815         double* second_gauss_area_coord =  NULL;
    1816         double* third_gauss_area_coord  =  NULL;
    1817         double* gauss_weights           =  NULL;
    1818         double  gauss_weight;
    1819         double  gauss_l1l2l3[3];
    1820 
    1821 
    1822         /* surface normal: */
    1823         double x4,y4,z4;
    1824         double x5,y5,z5;
    1825         double x6,y6,z6;
    1826         double v46[3];
    1827         double v56[3];
    1828         double normal[3];
    1829         double norm_normal;
    1830         double nz;
    1831 
    1832         /*Matrices: */
    1833         double DL_scalar;
    1834         double L[3];
    1835         double Jdet;
    1836 
    1837         /* local element matrices: */
    1838         double Ke_gg[numdof][numdof]={0.0}; //local element stiffness matrix
    1839         double Ke_gg_gaussian[numdof][numdof]; //stiffness matrix evaluated at the gaussian point.
    1840 
    1841         /* Get node coordinates and dof list: */
    1842         GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
    1843         GetDofList(&doflist[0],&numberofdofspernode);
    1844 
    1845         /* Get gaussian points and weights (make this a statically initialized list of points? fstd): */
    1846         GaussTria( &num_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &gauss_weights, 2);
    1847 
    1848         /*Build normal vector to the surface:*/
    1849 
    1850         x4=xyz_list[0][0];
    1851         y4=xyz_list[0][1];
    1852         z4=xyz_list[0][2];
    1853 
    1854         x5=xyz_list[1][0];
    1855         y5=xyz_list[1][1];
    1856         z5=xyz_list[1][2];
    1857 
    1858         x6=xyz_list[2][0];
    1859         y6=xyz_list[2][1];
    1860         z6=xyz_list[2][2];
    1861 
    1862         v46[0]=x4-x6;
    1863         v46[1]=y4-y6;
    1864         v46[2]=z4-z6;
    1865 
    1866         v56[0]=x5-x6;
    1867         v56[1]=y5-y6;
    1868         v56[2]=z5-z6;
    1869 
    1870         normal[0]=(y4-y6)*(z5-z6)-(z4-z6)*(y5-y6);
    1871         normal[1]=(z4-z6)*(x5-x6)-(x4-x6)*(z5-z6);
    1872         normal[2]=(x4-x6)*(y5-y6)-(y4-y6)*(x5-x6);
    1873 
    1874         norm_normal=sqrt(pow(normal[0],(double)2)+pow(normal[1],(double)2)+pow(normal[2],(double)2));
    1875         nz=1.0/norm_normal*normal[2];
    1876 
    1877         /* Start  looping on the number of gaussian points: */
    1878         for (ig=0; ig<num_gauss; ig++){
    1879                 /*Pick up the gaussian point: */
    1880                 gauss_weight=*(gauss_weights+ig);
    1881                 gauss_l1l2l3[0]=*(first_gauss_area_coord+ig);
    1882                 gauss_l1l2l3[1]=*(second_gauss_area_coord+ig);
    1883                 gauss_l1l2l3[2]=*(third_gauss_area_coord+ig);
    1884 
    1885                 /* Get Jacobian determinant: */
    1886                 GetJacobianDeterminant3d(&Jdet, &xyz_list[0][0],gauss_l1l2l3);
    1887 
    1888                 //Get L matrix if viscous basal drag present:
    1889                 GetL(&L[0], &xyz_list[0][0], gauss_l1l2l3,NDOF1);
    1890 
    1891                 /**********************Do not forget the sign**********************************/
    1892                 DL_scalar=- gauss_weight*Jdet*nz;
    1893                 /******************************************************************************/
    1894 
    1895                 /*  Do the triple producte tL*D*L: */
    1896                 TripleMultiply( L,1,3,1,
    1897                                         &DL_scalar,1,1,0,
    1898                                         L,1,3,0,
    1899                                         &Ke_gg_gaussian[0][0],0);
    1900 
    1901                 /* Add the Ke_gg_gaussian, onto Ke_gg: */
    1902                 for( i=0; i<numdof; i++) for(j=0;j<numdof;j++) Ke_gg[i][j]+=Ke_gg_gaussian[i][j];
    1903 
    1904 
    1905         } //for (ig=0; ig<num_gauss; ig++)
    1906 
    1907         /*Add Ke_gg to global matrix Kgg: */
    1908         MatSetValues(Kgg,numdof,doflist,numdof,doflist,(const double*)Ke_gg,ADD_VALUES);
    1909 
    1910 cleanup_and_return:
    1911         xfree((void**)&first_gauss_area_coord);
    1912         xfree((void**)&second_gauss_area_coord);
    1913         xfree((void**)&third_gauss_area_coord);
    1914         xfree((void**)&gauss_weights);
    1915 }
    1916 /*}}}*/
    1917 /*FUNCTION Tria::CreateKMatrixMelting {{{1*/
    1918 void  Tria::CreateKMatrixMelting(Mat Kgg){
    1919 
    1920         /*indexing: */
    1921         int i,j;
    1922 
    1923         const int  numgrids=3;
    1924         const int  NDOF1=1;
    1925         const int  numdof=numgrids*NDOF1;
    1926         int        doflist[numdof];
    1927         int        numberofdofspernode;
    1928 
    1929         /*Grid data: */
    1930         double     xyz_list[numgrids][3];
    1931 
    1932         /*Material constants */
    1933         double     heatcapacity,latentheat;
    1934 
    1935         /* gaussian points: */
    1936         int     num_area_gauss,ig;
    1937         double* gauss_weights  =  NULL;
    1938         double* first_gauss_area_coord  =  NULL;
    1939         double* second_gauss_area_coord =  NULL;
    1940         double* third_gauss_area_coord  =  NULL;
    1941         double  gauss_weight;
    1942         double  gauss_coord[3];
    1943 
    1944         /*matrices: */
    1945         double     Jdet;
    1946         double     D_scalar;
    1947         double     K_terms[numdof][numdof]={0.0};
    1948         double     L[3];
    1949         double     tLD[3];
    1950         double     Ke_gaussian[numdof][numdof]={0.0};
    1951 
    1952         /*Recover constants of ice */
    1953         latentheat=matpar->GetLatentHeat();
    1954         heatcapacity=matpar->GetHeatCapacity();
    1955 
    1956         /* Get node coordinates and dof list: */
    1957         GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
    1958         GetDofList(&doflist[0],&numberofdofspernode);
    1959 
    1960         /* Get gaussian points and weights: */
    1961         GaussTria (&num_area_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &gauss_weights, 2);
    1962 
    1963         /* Start looping on the number of gauss  (nodes on the bedrock) */
    1964         for (ig=0; ig<num_area_gauss; ig++){
    1965                 gauss_weight=*(gauss_weights+ig);
    1966                 gauss_coord[0]=*(first_gauss_area_coord+ig);
    1967                 gauss_coord[1]=*(second_gauss_area_coord+ig);
    1968                 gauss_coord[2]=*(third_gauss_area_coord+ig);
    1969 
    1970                 //Get the Jacobian determinant
    1971                 GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0], gauss_coord);
    1972 
    1973                 /*Get L matrix : */
    1974                 GetL(&L[0], &xyz_list[0][0], gauss_coord,NDOF1);
    1975 
    1976                 /*Calculate DL on gauss point */
    1977                 D_scalar=latentheat/heatcapacity*gauss_weight*Jdet;
    1978 
    1979                 /*  Do the triple product tL*D*L: */
    1980                 MatrixMultiply(&L[0],numdof,1,0,&D_scalar,1,1,0,&tLD[0],0);
    1981                 MatrixMultiply(&tLD[0],numdof,1,0,&L[0],1,numdof,0,&Ke_gaussian[0][0],0);
    1982 
    1983                 for(i=0;i<numgrids;i++){
    1984                         for(j=0;j<numgrids;j++){
    1985                                 K_terms[i][j]+=Ke_gaussian[i][j];
    1986                         }
    1987                 }
    1988         }
    1989 
    1990         /*Add Ke_gg to global matrix Kgg: */
    1991         MatSetValues(Kgg,numdof,doflist,numdof,doflist,(const double*)K_terms,ADD_VALUES);
    1992 
    1993 cleanup_and_return:
    1994         xfree((void**)&first_gauss_area_coord);
    1995         xfree((void**)&second_gauss_area_coord);
    1996         xfree((void**)&third_gauss_area_coord);
    1997         xfree((void**)&gauss_weights);
    1998 
    1999 }
    2000 /*}}}*/
    2001 /*FUNCTION Tria::CreateKMatrixPrognostic {{{1*/
    2002 void  Tria::CreateKMatrixPrognostic(Mat Kgg){
    2003 
    2004         /* local declarations */
    2005         int             i,j;
    2006 
    2007         /* node data: */
    2008         const int    numgrids=3;
    2009         const int    NDOF1=1;
    2010         const int    numdof=NDOF1*numgrids;
    2011         double       xyz_list[numgrids][3];
    2012         int          doflist[numdof];
    2013         int          numberofdofspernode;
    2014 
    2015         /* gaussian points: */
    2016         int     num_gauss,ig;
    2017         double* first_gauss_area_coord  =  NULL;
    2018         double* second_gauss_area_coord =  NULL;
    2019         double* third_gauss_area_coord  =  NULL;
    2020         double* gauss_weights           =  NULL;
    2021         double  gauss_weight;
    2022         double  gauss_l1l2l3[3];
    2023 
    2024         /* matrices: */
    2025         double L[numgrids];
    2026         double B[2][numgrids];
    2027         double Bprime[2][numgrids];
    2028         double DL[2][2]={0.0};
    2029         double DLprime[2][2]={0.0};
    2030         double DL_scalar;
    2031         double Ke_gg[numdof][numdof]={0.0};
    2032         double Ke_gg_gaussian[numdof][numdof]={0.0};
    2033         double Ke_gg_thickness1[numdof][numdof]={0.0};
    2034         double Ke_gg_thickness2[numdof][numdof]={0.0};
    2035         double Jdettria;
    2036 
    2037         /*input parameters for structural analysis (diagnostic): */
    2038         double  dvx[2];
    2039         double  dvy[2];
    2040         double  vx,vy;
    2041         double  dvxdx,dvydy;
    2042         double  v_gauss[2]={0.0};
    2043         double  K[2][2]={0.0};
    2044         double  KDL[2][2]={0.0};
    2045         int     dofs[2]={0,1};
    2046         int     found;
    2047 
    2048         /*parameters: */
    2049         double dt;
    2050         bool artdiff;
    2051 
    2052         /*retrieve some parameters: */
    2053         this->parameters->FindParam(&dt,DtEnum);
    2054         this->parameters->FindParam(&artdiff,ArtDiffEnum);
    2055 
    2056         /* Get node coordinates and dof list: */
    2057         GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
    2058         GetDofList(&doflist[0],&numberofdofspernode);
    2059 
    2060         //Create Artificial diffusivity once for all if requested
    2061         if(artdiff){
    2062                 //Get the Jacobian determinant
    2063                 gauss_l1l2l3[0]=ONETHIRD; gauss_l1l2l3[1]=ONETHIRD; gauss_l1l2l3[2]=ONETHIRD;
    2064                 GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss_l1l2l3);
    2065 
    2066                 //Build K matrix (artificial diffusivity matrix)
    2067                 inputs->GetParameterAverage(&v_gauss[0],VxAverageEnum);
    2068                 inputs->GetParameterAverage(&v_gauss[1],VyAverageEnum);
    2069 
    2070                 K[0][0]=pow(Jdettria,(double).5)/2.0*fabs(v_gauss[0]);
    2071                 K[1][1]=pow(Jdettria,(double).5)/2.0*fabs(v_gauss[1]);
    2072         }
    2073 
    2074         /* Get gaussian points and weights (make this a statically initialized list of points? fstd): */
    2075         GaussTria( &num_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &gauss_weights, 2);
    2076 
    2077         /* Start  looping on the number of gaussian points: */
    2078         for (ig=0; ig<num_gauss; ig++){
    2079 
    2080                 /*Pick up the gaussian point: */
    2081                 gauss_weight=*(gauss_weights+ig);
    2082                 gauss_l1l2l3[0]=*(first_gauss_area_coord+ig);
    2083                 gauss_l1l2l3[1]=*(second_gauss_area_coord+ig);
    2084                 gauss_l1l2l3[2]=*(third_gauss_area_coord+ig);
    2085 
    2086                 /* Get Jacobian determinant: */
    2087                 GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss_l1l2l3);
    2088 
    2089                 /*Get L matrix: */
    2090                 GetL(&L[0], &xyz_list[0][0], gauss_l1l2l3,numberofdofspernode);
    2091 
    2092                 DL_scalar=gauss_weight*Jdettria;
    2093 
    2094                 /*  Do the triple product tL*D*L: */
    2095                 TripleMultiply( &L[0],1,numdof,1,
    2096                                         &DL_scalar,1,1,0,
    2097                                         &L[0],1,numdof,0,
    2098                                         &Ke_gg_gaussian[0][0],0);
    2099 
    2100                 /*Get B  and B prime matrix: */
    2101                 GetB_prog(&B[0][0], &xyz_list[0][0], gauss_l1l2l3);
    2102                 GetBPrime_prog(&Bprime[0][0], &xyz_list[0][0], gauss_l1l2l3);
    2103 
    2104                 //Get vx, vy and their derivatives at gauss point
    2105                 inputs->GetParameterValue(&vx,&gauss_l1l2l3[0],VxAverageEnum);
    2106                 inputs->GetParameterValue(&vy,&gauss_l1l2l3[0],VyAverageEnum);
    2107 
    2108                 inputs->GetParameterDerivativeValue(&dvx[0],&xyz_list[0][0],&gauss_l1l2l3[0],VxAverageEnum);
    2109                 inputs->GetParameterDerivativeValue(&dvy[0],&xyz_list[0][0],&gauss_l1l2l3[0],VyAverageEnum);
    2110 
    2111                 dvxdx=dvx[0];
    2112                 dvydy=dvy[1];
    2113 
    2114                 DL_scalar=dt*gauss_weight*Jdettria;
    2115 
    2116                 //Create DL and DLprime matrix
    2117                 DL[0][0]=DL_scalar*dvxdx;
    2118                 DL[1][1]=DL_scalar*dvydy;
    2119 
    2120                 DLprime[0][0]=DL_scalar*vx;
    2121                 DLprime[1][1]=DL_scalar*vy;
    2122 
    2123                 //Do the triple product tL*D*L.
    2124                 //Ke_gg_thickness=B'*DL*B+B'*DLprime*Bprime;
    2125 
    2126                 TripleMultiply( &B[0][0],2,numdof,1,
    2127                                         &DL[0][0],2,2,0,
    2128                                         &B[0][0],2,numdof,0,
    2129                                         &Ke_gg_thickness1[0][0],0);
    2130 
    2131                 TripleMultiply( &B[0][0],2,numdof,1,
    2132                                         &DLprime[0][0],2,2,0,
    2133                                         &Bprime[0][0],2,numdof,0,
    2134                                         &Ke_gg_thickness2[0][0],0);
    2135 
    2136                 /* Add the Ke_gg_gaussian, and optionally Ke_gg_drag_gaussian onto Ke_gg: */
    2137                 for( i=0; i<numdof; i++) for(j=0;j<numdof;j++) Ke_gg[i][j]+=Ke_gg_gaussian[i][j];
    2138                 for( i=0; i<numdof; i++) for(j=0;j<numdof;j++) Ke_gg[i][j]+=Ke_gg_thickness1[i][j];
    2139                 for( i=0; i<numdof; i++) for(j=0;j<numdof;j++) Ke_gg[i][j]+=Ke_gg_thickness2[i][j];
    2140 
    2141                 if(artdiff){
    2142 
    2143                         /* Compute artificial diffusivity */
    2144                         KDL[0][0]=DL_scalar*K[0][0];
    2145                         KDL[1][1]=DL_scalar*K[1][1];
    2146 
    2147                         TripleMultiply( &Bprime[0][0],2,numdof,1,
    2148                                                 &KDL[0][0],2,2,0,
    2149                                                 &Bprime[0][0],2,numdof,0,
    2150                                                 &Ke_gg_gaussian[0][0],0);
    2151 
    2152                         /* Add artificial diffusivity matrix */
    2153                         for( i=0; i<numdof; i++) for(j=0;j<numdof;j++) Ke_gg[i][j]+=Ke_gg_gaussian[i][j];
    2154 
    2155                 }
    2156 
    2157         } // for (ig=0; ig<num_gauss; ig++)
    2158 
    2159         /*Add Ke_gg to global matrix Kgg: */
    2160         MatSetValues(Kgg,numdof,doflist,numdof,doflist,(const double*)Ke_gg,ADD_VALUES);
    2161 
    2162 
    2163 cleanup_and_return:
    2164         xfree((void**)&first_gauss_area_coord);
    2165         xfree((void**)&second_gauss_area_coord);
    2166         xfree((void**)&third_gauss_area_coord);
    2167         xfree((void**)&gauss_weights);
    2168 
    2169 }
    2170 /*}}}*/
    2171 /*FUNCTION Tria::CreateKMatrixPrognostic2 {{{1*/
    2172 void  Tria::CreateKMatrixPrognostic2(Mat Kgg){
    2173 
    2174         /* local declarations */
    2175         int             i,j;
    2176 
    2177         /* node data: */
    2178         const int    numgrids=3;
    2179         const int    NDOF1=1;
    2180         const int    numdof=NDOF1*numgrids;
    2181         double       xyz_list[numgrids][3];
    2182         int          doflist[numdof];
    2183         int          numberofdofspernode;
    2184 
    2185         /* gaussian points: */
    2186         int     num_gauss,ig;
    2187         double* first_gauss_area_coord  =  NULL;
    2188         double* second_gauss_area_coord =  NULL;
    2189         double* third_gauss_area_coord  =  NULL;
    2190         double* gauss_weights           =  NULL;
    2191         double  gauss_weight;
    2192         double  gauss_l1l2l3[3];
    2193 
    2194         /* matrices: */
    2195         double L[numgrids];
    2196         double B[2][numgrids];
    2197         double Bprime[2][numgrids];
    2198         double DL[2][2]={0.0};
    2199         double DLprime[2][2]={0.0};
    2200         double DL_scalar;
    2201         double Ke_gg[numdof][numdof]={0.0};
    2202         double Ke_gg1[numdof][numdof]={0.0};
    2203         double Ke_gg2[numdof][numdof]={0.0};
    2204         double Jdettria;
    2205 
    2206         /*input parameters for structural analysis (diagnostic): */
    2207         double  vx,vy;
    2208         int     dofs[1]={0};
    2209         int     found;
    2210 
    2211         /*parameters: */
    2212         double dt;
    2213 
    2214         /*retrieve some parameters: */
    2215         this->parameters->FindParam(&dt,DtEnum);
    2216 
    2217         /* Get node coordinates and dof list: */
    2218         GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
    2219         GetDofList(&doflist[0],&numberofdofspernode);
    2220 
    2221         /* Get gaussian points and weights (make this a statically initialized list of points? fstd): */
    2222         GaussTria( &num_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &gauss_weights, 2);
    2223 
    2224         /* Start  looping on the number of gaussian points: */
    2225         for (ig=0; ig<num_gauss; ig++){
    2226 
    2227                 /*Pick up the gaussian point: */
    2228                 gauss_weight=*(gauss_weights+ig);
    2229                 gauss_l1l2l3[0]=*(first_gauss_area_coord+ig);
    2230                 gauss_l1l2l3[1]=*(second_gauss_area_coord+ig);
    2231                 gauss_l1l2l3[2]=*(third_gauss_area_coord+ig);
    2232 
    2233                 /* Get Jacobian determinant: */
    2234                 GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss_l1l2l3);
    2235 
    2236                 /*Get L matrix: */
    2237                 GetL(&L[0], &xyz_list[0][0], gauss_l1l2l3,numberofdofspernode);
    2238 
    2239                 DL_scalar=gauss_weight*Jdettria;
    2240 
    2241                 /*  Do the triple product tL*D*L: */
    2242                 TripleMultiply( &L[0],1,numdof,1,
    2243                                         &DL_scalar,1,1,0,
    2244                                         &L[0],1,numdof,0,
    2245                                         &Ke_gg1[0][0],0);
    2246 
    2247                 /*Get B  and B prime matrix: */
    2248                 /*WARNING: B and Bprime are inverted compared to usual prognostic!!!!*/
    2249                 GetB_prog(&Bprime[0][0], &xyz_list[0][0], gauss_l1l2l3);
    2250                 GetBPrime_prog(&B[0][0], &xyz_list[0][0], gauss_l1l2l3);
    2251 
    2252                 //Get vx, vy and their derivatives at gauss point
    2253                 inputs->GetParameterValue(&vx,&gauss_l1l2l3[0],VxAverageEnum);
    2254                 inputs->GetParameterValue(&vy,&gauss_l1l2l3[0],VyAverageEnum);
    2255 
    2256                 DL_scalar=-dt*gauss_weight*Jdettria;
    2257 
    2258                 DLprime[0][0]=DL_scalar*vx;
    2259                 DLprime[1][1]=DL_scalar*vy;
    2260 
    2261                 //Do the triple product tL*D*L.
    2262                 TripleMultiply( &B[0][0],2,numdof,1,
    2263                                         &DLprime[0][0],2,2,0,
    2264                                         &Bprime[0][0],2,numdof,0,
    2265                                         &Ke_gg2[0][0],0);
    2266 
    2267                 /* Add the Ke_gg_gaussian, and optionally Ke_gg_drag_gaussian onto Ke_gg: */
    2268                 for( i=0; i<numdof; i++) for(j=0;j<numdof;j++) Ke_gg[i][j]+=Ke_gg1[i][j];
    2269                 for( i=0; i<numdof; i++) for(j=0;j<numdof;j++) Ke_gg[i][j]+=Ke_gg2[i][j];
    2270 
    2271         } // for (ig=0; ig<num_gauss; ig++)
    2272 
    2273         /*Add Ke_gg to global matrix Kgg: */
    2274         MatSetValues(Kgg,numdof,doflist,numdof,doflist,(const double*)Ke_gg,ADD_VALUES);
    2275 
    2276 
    2277 cleanup_and_return:
    2278         xfree((void**)&first_gauss_area_coord);
    2279         xfree((void**)&second_gauss_area_coord);
    2280         xfree((void**)&third_gauss_area_coord);
    2281         xfree((void**)&gauss_weights);
    2282 
    2283 }
    2284 /*}}}*/
    2285 /*FUNCTION Tria::CreateKMatrixSlopeCompute {{{1*/
    2286 
    2287 void  Tria::CreateKMatrixSlopeCompute(Mat Kgg){
    2288 
    2289         /* local declarations */
    2290         int             i,j;
    2291 
    2292         /* node data: */
    2293         const int    numgrids=3;
    2294         const int    NDOF1=1;
    2295         const int    numdof=NDOF1*numgrids;
    2296         double       xyz_list[numgrids][3];
    2297         int          doflist[numdof];
    2298         int          numberofdofspernode;
    2299        
    2300         /* gaussian points: */
    2301         int     num_gauss,ig;
    2302         double* first_gauss_area_coord  =  NULL;
    2303         double* second_gauss_area_coord =  NULL;
    2304         double* third_gauss_area_coord  =  NULL;
    2305         double* gauss_weights           =  NULL;
    2306         double  gauss_weight;
    2307         double  gauss_l1l2l3[3];
    2308 
    2309         /* matrices: */
    2310         double L[1][3];
    2311         double DL_scalar;
    2312 
    2313         /* local element matrices: */
    2314         double Ke_gg[numdof][numdof]={0.0}; //local element stiffness matrix
    2315         double Ke_gg_gaussian[numdof][numdof]; //stiffness matrix evaluated at the gaussian point.
    2316        
    2317         double Jdet;
    2318 
    2319         /* Get node coordinates and dof list: */
    2320         GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
    2321         GetDofList(&doflist[0],&numberofdofspernode);
    2322 
    2323         /* Get gaussian points and weights (make this a statically initialized list of points? fstd): */
    2324         GaussTria( &num_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &gauss_weights, 2);
    2325 
    2326         /* Start  looping on the number of gaussian points: */
    2327         for (ig=0; ig<num_gauss; ig++){
    2328                 /*Pick up the gaussian point: */
    2329                 gauss_weight=*(gauss_weights+ig);
    2330                 gauss_l1l2l3[0]=*(first_gauss_area_coord+ig);
    2331                 gauss_l1l2l3[1]=*(second_gauss_area_coord+ig);
    2332                 gauss_l1l2l3[2]=*(third_gauss_area_coord+ig);
    2333 
    2334                
    2335                 /*Get L matrix: */
    2336                 GetL(&L[0][0], &xyz_list[0][0], gauss_l1l2l3,NDOF1);
    2337 
    2338                 /* Get Jacobian determinant: */
    2339                 GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0],gauss_l1l2l3);
    2340                
    2341                 DL_scalar=gauss_weight*Jdet;
    2342 
    2343                 /*  Do the triple producte tL*D*L: */
    2344                 TripleMultiply( &L[0][0],1,3,1,
    2345                                         &DL_scalar,1,1,0,
    2346                                         &L[0][0],1,3,0,
    2347                                         &Ke_gg_gaussian[0][0],0);
    2348 
    2349                 /* Add the Ke_gg_gaussian, and optionally Ke_gg_drag_gaussian onto Ke_gg: */
    2350                 for( i=0; i<numdof; i++) for(j=0;j<numdof;j++) Ke_gg[i][j]+=Ke_gg_gaussian[i][j];
    2351         } //for (ig=0; ig<num_gauss; ig++
    2352 
    2353         /*Add Ke_gg to global matrix Kgg: */
    2354         MatSetValues(Kgg,numdof,doflist,numdof,doflist,(const double*)Ke_gg,ADD_VALUES);
    2355                
    2356         cleanup_and_return:
    2357         xfree((void**)&first_gauss_area_coord);
    2358         xfree((void**)&second_gauss_area_coord);
    2359         xfree((void**)&third_gauss_area_coord);
    2360         xfree((void**)&gauss_weights);
    2361 }
    2362 /*}}}*/
    2363 /*FUNCTION Tria::CreateKMatrixThermal {{{1*/
    2364 void  Tria::CreateKMatrixThermal(Mat Kgg){
    2365 
    2366         int i,j;
    2367         int found=0;
    2368        
    2369         /* node data: */
    2370         const int    numgrids=3;
    2371         const int    NDOF1=1;
    2372         const int    numdof=NDOF1*numgrids;
    2373         double       xyz_list[numgrids][3];
    2374         int          doflist[numdof];
    2375         int          numberofdofspernode;
    2376 
    2377         double mixed_layer_capacity;
    2378         double thermal_exchange_velocity;
    2379         double rho_water;
    2380         double rho_ice;
    2381         double heatcapacity;
    2382 
    2383         int     num_gauss,ig;
    2384         double* first_gauss_area_coord  =  NULL;
    2385         double* second_gauss_area_coord =  NULL;
    2386         double* third_gauss_area_coord  =  NULL;
    2387         double* gauss_weights           =  NULL;
    2388         double  gauss_weight;
    2389         double  gauss_coord[3];
    2390 
    2391         /*matrices: */
    2392         double  Jdet;
    2393         double  K_terms[numdof][numdof]={0.0};
    2394         double  Ke_gaussian[numdof][numdof]={0.0};
    2395         double  l1l2l3[numgrids];
    2396         double     tl1l2l3D[3];
    2397         double  D_scalar;
    2398 
    2399         /*parameters: */
    2400         double dt;
    2401 
    2402         /*retrieve some parameters: */
    2403         this->parameters->FindParam(&dt,DtEnum);
    2404 
    2405         /* Get node coordinates and dof list: */
    2406         GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
    2407         GetDofList(&doflist[0],&numberofdofspernode);
    2408 
    2409         //recover material parameters
    2410         mixed_layer_capacity=matpar->GetMixedLayerCapacity();
    2411         thermal_exchange_velocity=matpar->GetThermalExchangeVelocity();
    2412         rho_water=matpar->GetRhoWater();
    2413         rho_ice=matpar->GetRhoIce();
    2414         heatcapacity=matpar->GetHeatCapacity();
    2415 
    2416 
    2417         GaussTria (&num_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &gauss_weights, 2);
    2418 
    2419         /* Start looping on the number of gauss (nodes on the bedrock) */
    2420         for (ig=0; ig<num_gauss; ig++){
    2421                 gauss_weight=*(gauss_weights+ig);
    2422                 gauss_coord[0]=*(first_gauss_area_coord+ig);
    2423                 gauss_coord[1]=*(second_gauss_area_coord+ig);
    2424                 gauss_coord[2]=*(third_gauss_area_coord+ig);
    2425                
    2426                 //Get the Jacobian determinant
    2427                 GetJacobianDeterminant3d(&Jdet, &xyz_list[0][0], gauss_coord);
    2428                
    2429                 /*Get nodal functions values: */
    2430                 GetNodalFunctions(&l1l2l3[0], gauss_coord);
    2431                                
    2432                 /*Calculate DL on gauss point */
    2433                 D_scalar=gauss_weight*Jdet*rho_water*mixed_layer_capacity*thermal_exchange_velocity/(heatcapacity*rho_ice);
    2434                 if(dt){
    2435                         D_scalar=dt*D_scalar;
    2436                 }
    2437 
    2438                 /*  Do the triple product tL*D*L: */
    2439                 MatrixMultiply(&l1l2l3[0],numdof,1,0,&D_scalar,1,1,0,&tl1l2l3D[0],0);
    2440                 MatrixMultiply(&tl1l2l3D[0],numdof,1,0,&l1l2l3[0],1,numdof,0,&Ke_gaussian[0][0],0);
    2441 
    2442                 for(i=0;i<3;i++){
    2443                         for(j=0;j<3;j++){
    2444                                 K_terms[i][j]+=Ke_gaussian[i][j];
    2445                         }
    2446                 }
    2447         }
    2448        
    2449         /*Add Ke_gg to global matrix Kgg: */
    2450         MatSetValues(Kgg,numdof,doflist,numdof,doflist,(const double*)K_terms,ADD_VALUES);
    2451 
    2452         cleanup_and_return:
    2453         xfree((void**)&first_gauss_area_coord);
    2454         xfree((void**)&second_gauss_area_coord);
    2455         xfree((void**)&third_gauss_area_coord);
    2456         xfree((void**)&gauss_weights);
    2457622
    2458623}
     
    2481646                CreatePVectorDiagnosticHutter( pg);
    2482647        }
    2483         else if (analysis_type==SlopeAnalysisEnum){
     648        else if (analysis_type==BedSlopeAnalysisEnum || analysis_type==SurfaceSlopeAnalysisEnum){
    2484649                CreatePVectorSlopeCompute( pg);
    2485650        }
     
    2502667                ISSMERROR("analysis %i (%s) not supported yet",analysis_type,EnumAsString(analysis_type));
    2503668        }
    2504 
    2505 }
    2506 /*}}}*/
    2507 /*FUNCTION Tria::CreatePVectorBalancedthickness {{{1*/
    2508 void  Tria::CreatePVectorBalancedthickness(Vec pg ){
    2509 
    2510 
    2511         /* local declarations */
    2512         int             i,j;
    2513 
    2514         /* node data: */
    2515         const int    numgrids=3;
    2516         const int    NDOF1=1;
    2517         const int    numdof=NDOF1*numgrids;
    2518         double       xyz_list[numgrids][3];
    2519         int          doflist[numdof];
    2520         int          numberofdofspernode;
    2521 
    2522         /* gaussian points: */
    2523         int     num_gauss,ig;
    2524         double* first_gauss_area_coord  =  NULL;
    2525         double* second_gauss_area_coord =  NULL;
    2526         double* third_gauss_area_coord  =  NULL;
    2527         double* gauss_weights           =  NULL;
    2528         double  gauss_weight;
    2529         double  gauss_l1l2l3[3];
    2530 
    2531         /* matrix */
    2532         double pe_g[numgrids]={0.0};
    2533         double L[numgrids];
    2534         double Jdettria;
    2535 
    2536         /*input parameters for structural analysis (diagnostic): */
    2537         double  accumulation_g;
    2538         double  melting_g;
    2539 
    2540         /* Get node coordinates and dof list: */
    2541         GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
    2542         GetDofList(&doflist[0],&numberofdofspernode);
    2543 
    2544         /* Get gaussian points and weights (make this a statically initialized list of points? fstd): */
    2545         GaussTria( &num_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &gauss_weights, 2);
    2546 
    2547         /* Start  looping on the number of gaussian points: */
    2548         for (ig=0; ig<num_gauss; ig++){
    2549                 /*Pick up the gaussian point: */
    2550                 gauss_weight=*(gauss_weights+ig);
    2551                 gauss_l1l2l3[0]=*(first_gauss_area_coord+ig);
    2552                 gauss_l1l2l3[1]=*(second_gauss_area_coord+ig);
    2553                 gauss_l1l2l3[2]=*(third_gauss_area_coord+ig);
    2554 
    2555                 /* Get Jacobian determinant: */
    2556                 GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss_l1l2l3);
    2557 
    2558                 /*Get L matrix: */
    2559                 GetL(&L[0], &xyz_list[0][0], gauss_l1l2l3,numberofdofspernode);
    2560 
    2561                 /* Get accumulation, melting at gauss point */
    2562                 inputs->GetParameterValue(&accumulation_g, &gauss_l1l2l3[0],AccumulationRateEnum);
    2563                 inputs->GetParameterValue(&melting_g, &gauss_l1l2l3[0],MeltingRateEnum);
    2564 
    2565                 /* Add value into pe_g: */
    2566                 for( i=0; i<numdof; i++) pe_g[i]+=Jdettria*gauss_weight*(accumulation_g-melting_g)*L[i];
    2567 
    2568         } // for (ig=0; ig<num_gauss; ig++)
    2569 
    2570         /*Add pe_g to global matrix Kgg: */
    2571         VecSetValues(pg,numdof,doflist,(const double*)pe_g,ADD_VALUES);
    2572 
    2573 cleanup_and_return:
    2574         xfree((void**)&first_gauss_area_coord);
    2575         xfree((void**)&second_gauss_area_coord);
    2576         xfree((void**)&third_gauss_area_coord);
    2577         xfree((void**)&gauss_weights);
    2578 
    2579 }
    2580 /*}}}*/
    2581 /*FUNCTION Tria::CreatePVectorBalancedthickness2 {{{1*/
    2582 void  Tria::CreatePVectorBalancedthickness2(Vec pg){
    2583 
    2584 
    2585         /* local declarations */
    2586         int             i,j;
    2587 
    2588         /* node data: */
    2589         const int    numgrids=3;
    2590         const int    NDOF1=1;
    2591         const int    numdof=NDOF1*numgrids;
    2592         double       xyz_list[numgrids][3];
    2593         int          doflist[numdof];
    2594         int          numberofdofspernode;
    2595 
    2596         /* gaussian points: */
    2597         int     num_gauss,ig;
    2598         double* first_gauss_area_coord  =  NULL;
    2599         double* second_gauss_area_coord =  NULL;
    2600         double* third_gauss_area_coord  =  NULL;
    2601         double* gauss_weights           =  NULL;
    2602         double  gauss_weight;
    2603         double  gauss_l1l2l3[3];
    2604 
    2605         /* matrix */
    2606         double pe_g[numgrids]={0.0};
    2607         double L[numgrids];
    2608         double Jdettria;
    2609 
    2610         /*input parameters for structural analysis (diagnostic): */
    2611         double  accumulation_g;
    2612         double  melting_g;
    2613         double  dhdt_g;
    2614 
    2615         /* Get node coordinates and dof list: */
    2616         GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
    2617         GetDofList(&doflist[0],&numberofdofspernode);
    2618 
    2619         /* Get gaussian points and weights (make this a statically initialized list of points? fstd): */
    2620         GaussTria( &num_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &gauss_weights, 2);
    2621 
    2622         /* Start  looping on the number of gaussian points: */
    2623         for (ig=0; ig<num_gauss; ig++){
    2624                 /*Pick up the gaussian point: */
    2625                 gauss_weight=*(gauss_weights+ig);
    2626                 gauss_l1l2l3[0]=*(first_gauss_area_coord+ig);
    2627                 gauss_l1l2l3[1]=*(second_gauss_area_coord+ig);
    2628                 gauss_l1l2l3[2]=*(third_gauss_area_coord+ig);
    2629 
    2630                 /* Get Jacobian determinant: */
    2631                 GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss_l1l2l3);
    2632 
    2633                 /*Get L matrix: */
    2634                 GetL(&L[0], &xyz_list[0][0], gauss_l1l2l3,numberofdofspernode);
    2635 
    2636                 /* Get accumulation, melting and thickness at gauss point */
    2637                 inputs->GetParameterValue(&accumulation_g, &gauss_l1l2l3[0],AccumulationRateEnum);
    2638                 inputs->GetParameterValue(&melting_g, &gauss_l1l2l3[0],MeltingRateEnum);
    2639                 inputs->GetParameterValue(&dhdt_g, &gauss_l1l2l3[0],DhDtEnum);
    2640 
    2641                 /* Add value into pe_g: */
    2642                 for( i=0; i<numdof; i++) pe_g[i]+=Jdettria*gauss_weight*(accumulation_g-melting_g+dhdt_g)*L[i];
    2643 
    2644         } // for (ig=0; ig<num_gauss; ig++)
    2645 
    2646         /*Add pe_g to global matrix Kgg: */
    2647         VecSetValues(pg,numdof,doflist,(const double*)pe_g,ADD_VALUES);
    2648 
    2649 cleanup_and_return:
    2650         xfree((void**)&first_gauss_area_coord);
    2651         xfree((void**)&second_gauss_area_coord);
    2652         xfree((void**)&third_gauss_area_coord);
    2653         xfree((void**)&gauss_weights);
    2654 
    2655 }
    2656 /*}}}*/
    2657 /*FUNCTION Tria::CreatePVectorBalancedvelocities {{{1*/
    2658 void  Tria::CreatePVectorBalancedvelocities(Vec pg){
    2659 
    2660 
    2661         /* local declarations */
    2662         int             i,j;
    2663 
    2664         /* node data: */
    2665         const int    numgrids=3;
    2666         const int    NDOF1=1;
    2667         const int    numdof=NDOF1*numgrids;
    2668         double       xyz_list[numgrids][3];
    2669         int          doflist[numdof];
    2670         int          numberofdofspernode;
    2671 
    2672         /* gaussian points: */
    2673         int     num_gauss,ig;
    2674         double* first_gauss_area_coord  =  NULL;
    2675         double* second_gauss_area_coord =  NULL;
    2676         double* third_gauss_area_coord  =  NULL;
    2677         double* gauss_weights           =  NULL;
    2678         double  gauss_weight;
    2679         double  gauss_l1l2l3[3];
    2680 
    2681         /* matrix */
    2682         double pe_g[numgrids]={0.0};
    2683         double L[numgrids];
    2684         double Jdettria;
    2685 
    2686         /*input parameters for structural analysis (diagnostic): */
    2687         double  accumulation_g;
    2688         double  melting_g;
    2689 
    2690         /* Get node coordinates and dof list: */
    2691         GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
    2692         GetDofList(&doflist[0],&numberofdofspernode);
    2693 
    2694         /* Get gaussian points and weights (make this a statically initialized list of points? fstd): */
    2695         GaussTria( &num_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &gauss_weights, 2);
    2696 
    2697         /* Start  looping on the number of gaussian points: */
    2698         for (ig=0; ig<num_gauss; ig++){
    2699                 /*Pick up the gaussian point: */
    2700                 gauss_weight=*(gauss_weights+ig);
    2701                 gauss_l1l2l3[0]=*(first_gauss_area_coord+ig);
    2702                 gauss_l1l2l3[1]=*(second_gauss_area_coord+ig);
    2703                 gauss_l1l2l3[2]=*(third_gauss_area_coord+ig);
    2704 
    2705                 /* Get Jacobian determinant: */
    2706                 GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss_l1l2l3);
    2707 
    2708                 /*Get L matrix: */
    2709                 GetL(&L[0], &xyz_list[0][0], gauss_l1l2l3,numberofdofspernode);
    2710 
    2711                 /* Get accumulation, melting at gauss point */
    2712                 inputs->GetParameterValue(&accumulation_g, &gauss_l1l2l3[0],AccumulationRateEnum);
    2713                 inputs->GetParameterValue(&melting_g, &gauss_l1l2l3[0],MeltingRateEnum);
    2714 
    2715                 /* Add value into pe_g: */
    2716                 for( i=0; i<numdof; i++) pe_g[i]+=Jdettria*gauss_weight*(accumulation_g-melting_g)*L[i];
    2717 
    2718         } // for (ig=0; ig<num_gauss; ig++)
    2719 
    2720         /*Add pe_g to global matrix Kgg: */
    2721         VecSetValues(pg,numdof,doflist,(const double*)pe_g,ADD_VALUES);
    2722 
    2723 cleanup_and_return:
    2724         xfree((void**)&first_gauss_area_coord);
    2725         xfree((void**)&second_gauss_area_coord);
    2726         xfree((void**)&third_gauss_area_coord);
    2727         xfree((void**)&gauss_weights);
    2728 
    2729 }
    2730 /*}}}*/
    2731 /*FUNCTION Tria::CreatePVectorDiagnosticBaseVert {{{1*/
    2732 void  Tria::CreatePVectorDiagnosticBaseVert(Vec pg){
    2733 
    2734         int             i,j;
    2735 
    2736         /* node data: */
    2737         const int    numgrids=3;
    2738         const int    NDOF1=1;
    2739         const int    numdof=NDOF1*numgrids;
    2740         double       xyz_list[numgrids][3];
    2741         int          doflist[numdof];
    2742         int          numberofdofspernode;
    2743 
    2744         /* gaussian points: */
    2745         int     num_gauss,ig;
    2746         double* first_gauss_area_coord  =  NULL;
    2747         double* second_gauss_area_coord =  NULL;
    2748         double* third_gauss_area_coord  =  NULL;
    2749         double* gauss_weights           =  NULL;
    2750         double  gauss_weight;
    2751         double  gauss_l1l2l3[3];
    2752 
    2753         /* Jacobian: */
    2754         double Jdet;
    2755 
    2756         /*nodal functions: */
    2757         double l1l2l3[3];
    2758 
    2759         /*element vector at the gaussian points: */
    2760         double  pe_g[numdof]={0.0};
    2761         double  pe_g_gaussian[numdof];
    2762 
    2763         /* matrices: */
    2764         double L[numgrids];
    2765 
    2766         /*input parameters for structural analysis (diagnostic): */
    2767         double  vx,vy;
    2768         double  meltingvalue;
    2769         double  slope[2];
    2770         double  dbdx,dbdy;
    2771 
    2772         /* Get node coordinates and dof list: */
    2773         GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
    2774         GetDofList(&doflist[0],&numberofdofspernode);
    2775 
    2776         /* Get gaussian points and weights (make this a statically initialized list of points? fstd): */
    2777         GaussTria( &num_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &gauss_weights, 2);
    2778 
    2779         /*For icesheets: */
    2780         /* Start  looping on the number of gaussian points: */
    2781         for (ig=0; ig<num_gauss; ig++){
    2782 
    2783                 /*Pick up the gaussian point: */
    2784                 gauss_weight=*(gauss_weights+ig);
    2785                 gauss_l1l2l3[0]=*(first_gauss_area_coord+ig);
    2786                 gauss_l1l2l3[1]=*(second_gauss_area_coord+ig);
    2787                 gauss_l1l2l3[2]=*(third_gauss_area_coord+ig);
    2788 
    2789                 /*Get melting at gaussian point: */
    2790                 inputs->GetParameterValue(&meltingvalue, &gauss_l1l2l3[0],MeltingRateEnum);
    2791 
    2792                 /*Get velocity at gaussian point: */
    2793                 inputs->GetParameterValue(&vx, &gauss_l1l2l3[0],VxEnum);
    2794                 inputs->GetParameterValue(&vy, &gauss_l1l2l3[0],VyEnum);
    2795 
    2796                 /*Get bed slope: */
    2797                 inputs->GetParameterDerivativeValue(&slope[0],&xyz_list[0][0],&gauss_l1l2l3[0],BedEnum);
    2798                 dbdx=slope[0];
    2799                 dbdy=slope[1];
    2800 
    2801                 /* Get Jacobian determinant: */
    2802                 GetJacobianDeterminant3d(&Jdet, &xyz_list[0][0],gauss_l1l2l3);
    2803 
    2804                 //Get L matrix if viscous basal drag present:
    2805                 GetL(&L[0], &xyz_list[0][0], gauss_l1l2l3,NDOF1);
    2806 
    2807 
    2808                 /*Build gaussian vector: */
    2809                 for(i=0;i<numgrids;i++){
    2810                         pe_g_gaussian[i]=-Jdet*gauss_weight*(vx*dbdx+vy*dbdy-meltingvalue)*L[i];
    2811                 }
    2812 
    2813                 /*Add pe_g_gaussian vector to pe_g: */
    2814                 for( i=0; i<numdof; i++)pe_g[i]+=pe_g_gaussian[i];
    2815 
    2816         }
    2817 
    2818         /*Add pe_g to global vector pg: */
    2819         VecSetValues(pg,numdof,doflist,(const double*)pe_g,ADD_VALUES);
    2820 
    2821 cleanup_and_return:
    2822         xfree((void**)&first_gauss_area_coord);
    2823         xfree((void**)&second_gauss_area_coord);
    2824         xfree((void**)&third_gauss_area_coord);
    2825         xfree((void**)&gauss_weights);
    2826 
    2827 }
    2828 /*}}}*/
    2829 /*FUNCTION Tria::CreatePVectorDiagnosticHoriz {{{1*/
    2830 void Tria::CreatePVectorDiagnosticHoriz( Vec pg){
    2831 
    2832         int             i,j;
    2833 
    2834         /* node data: */
    2835         const int    numgrids=3;
    2836         const int    numdof=2*numgrids;
    2837         const int    NDOF2=2;
    2838         double       xyz_list[numgrids][3];
    2839         int          doflist[numdof];
    2840         int          numberofdofspernode;
    2841        
    2842         /* parameters: */
    2843         double  plastic_stress;
    2844         double  slope[NDOF2];
    2845         double  driving_stress_baseline;
    2846 
    2847         /* gaussian points: */
    2848         int     num_gauss,ig;
    2849         double* first_gauss_area_coord  =  NULL;
    2850         double* second_gauss_area_coord =  NULL;
    2851         double* third_gauss_area_coord  =  NULL;
    2852         double* gauss_weights           =  NULL;
    2853         double  gauss_weight;
    2854         double  gauss_l1l2l3[3];
    2855 
    2856         /* Jacobian: */
    2857         double Jdet;
    2858 
    2859         /*nodal functions: */
    2860         double l1l2l3[3];
    2861 
    2862         /*element vector at the gaussian points: */
    2863         double  pe_g[numdof]={0.0};
    2864         double  pe_g_gaussian[numdof];
    2865 
    2866         /*input parameters for structural analysis (diagnostic): */
    2867         double  thickness;
    2868 
    2869         /*inputs: */
    2870         bool onwater;
    2871         int  drag_type;
    2872 
    2873         /*retrieve inputs :*/
    2874         inputs->GetParameterValue(&onwater,ElementOnWaterEnum);
    2875         inputs->GetParameterValue(&drag_type,DragTypeEnum);
    2876 
    2877         /*First, if we are on water, return empty vector: */
    2878         if(onwater)return;
    2879 
    2880         /* Get node coordinates and dof list: */
    2881         GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
    2882         GetDofList(&doflist[0],&numberofdofspernode);
    2883 
    2884 
    2885         /* Get gaussian points and weights: */
    2886         GaussTria( &num_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &gauss_weights, 2); /*We need higher order because our load is order 2*/
    2887 
    2888         /* Start  looping on the number of gaussian points: */
    2889         for (ig=0; ig<num_gauss; ig++){
    2890                 /*Pick up the gaussian point: */
    2891                 gauss_weight=*(gauss_weights+ig);
    2892                 gauss_l1l2l3[0]=*(first_gauss_area_coord+ig);
    2893                 gauss_l1l2l3[1]=*(second_gauss_area_coord+ig);
    2894                 gauss_l1l2l3[2]=*(third_gauss_area_coord+ig);
    2895 
    2896                 /*Compute thickness at gaussian point: */
    2897                 inputs->GetParameterValue(&thickness, &gauss_l1l2l3[0],ThicknessEnum);
    2898                 inputs->GetParameterDerivativeValue(&slope[0],&xyz_list[0][0],&gauss_l1l2l3[0],SurfaceEnum);
    2899                
    2900                 /*In case we have plastic basal drag, compute plastic stress at gaussian point from k1, k2 and k3 fields in the
    2901                  * element itself: */
    2902                 if(drag_type==1){
    2903                         inputs->GetParameterValue(&plastic_stress, &gauss_l1l2l3[0],DragCoefficientEnum);
    2904                 }
    2905 
    2906                 /* Get Jacobian determinant: */
    2907                 GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0],gauss_l1l2l3);
    2908                
    2909                  /*Get nodal functions: */
    2910                 GetNodalFunctions(l1l2l3, gauss_l1l2l3);
    2911 
    2912                 /*Compute driving stress: */
    2913                 driving_stress_baseline=matpar->GetRhoIce()*matpar->GetG()*thickness;
    2914 
    2915                 /*Build pe_g_gaussian vector: */
    2916                 if(drag_type==1){
    2917                         for (i=0;i<numgrids;i++){
    2918                                 for (j=0;j<NDOF2;j++){
    2919                                         pe_g_gaussian[i*NDOF2+j]=(-driving_stress_baseline*slope[j]-plastic_stress)*Jdet*gauss_weight*l1l2l3[i];
    2920                                 }
    2921                         }
    2922                 }
    2923                 else {
    2924                         for (i=0;i<numgrids;i++){
    2925                                 for (j=0;j<NDOF2;j++){
    2926                                         pe_g_gaussian[i*NDOF2+j]=-driving_stress_baseline*slope[j]*Jdet*gauss_weight*l1l2l3[i];
    2927                                 }
    2928                         }
    2929                 }
    2930 
    2931                 /*Add pe_g_gaussian vector to pe_g: */
    2932                 for( i=0; i<numdof; i++)pe_g[i]+=pe_g_gaussian[i];
    2933 
    2934         } //for (ig=0; ig<num_gauss; ig++)
    2935 
    2936         /*Add pe_g to global vector pg: */
    2937         VecSetValues(pg,numdof,doflist,(const double*)pe_g,ADD_VALUES);
    2938 
    2939         cleanup_and_return:
    2940         xfree((void**)&first_gauss_area_coord);
    2941         xfree((void**)&second_gauss_area_coord);
    2942         xfree((void**)&third_gauss_area_coord);
    2943         xfree((void**)&gauss_weights);
    2944 
    2945 }
    2946 /*}}}*/
    2947 /*FUNCTION Tria::CreatePVectorDiagnosticHutter{{{1*/
    2948 void  Tria::CreatePVectorDiagnosticHutter(Vec pg){
    2949 
    2950         /*Collapsed formulation: */
    2951         Sing*  sing=NULL;
    2952         int    i;
    2953 
    2954         /*flags: */
    2955         bool onwater;
    2956 
    2957         /*recover some inputs: */
    2958         inputs->GetParameterValue(&onwater,ElementOnWaterEnum);
    2959 
    2960         /*If on water, skip: */
    2961         if(onwater)return;
    2962 
    2963         /*Spawn 3 sing elements: */
    2964         for(i=0;i<3;i++){
    2965                 sing=(Sing*)SpawnSing(i);
    2966                 sing->CreatePVector(pg);
    2967         }
    2968 
    2969         /*clean up*/
    2970         delete sing;
    2971 
    2972 }
    2973 /*}}}*/
    2974 /*FUNCTION Tria::CreatePVectorPrognostic {{{1*/
    2975 void  Tria::CreatePVectorPrognostic(Vec pg){
    2976 
    2977 
    2978         /* local declarations */
    2979         int             i,j;
    2980 
    2981         /* node data: */
    2982         const int    numgrids=3;
    2983         const int    NDOF1=1;
    2984         const int    numdof=NDOF1*numgrids;
    2985         double       xyz_list[numgrids][3];
    2986         int          doflist[numdof];
    2987         int          numberofdofspernode;
    2988 
    2989         /* gaussian points: */
    2990         int     num_gauss,ig;
    2991         double* first_gauss_area_coord  =  NULL;
    2992         double* second_gauss_area_coord =  NULL;
    2993         double* third_gauss_area_coord  =  NULL;
    2994         double* gauss_weights           =  NULL;
    2995         double  gauss_weight;
    2996         double  gauss_l1l2l3[3];
    2997 
    2998         /* matrix */
    2999         double pe_g[numgrids]={0.0};
    3000         double L[numgrids];
    3001         double Jdettria;
    3002 
    3003         /*input parameters for structural analysis (diagnostic): */
    3004         double  accumulation_g;
    3005         double  melting_g;
    3006         double  thickness_g;
    3007 
    3008         /*parameters: */
    3009         double  dt;
    3010 
    3011         /*retrieve some parameters: */
    3012         this->parameters->FindParam(&dt,DtEnum);
    3013 
    3014         /* Get node coordinates and dof list: */
    3015         GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
    3016         GetDofList(&doflist[0],&numberofdofspernode);
    3017 
    3018         /* Get gaussian points and weights (make this a statically initialized list of points? fstd): */
    3019         GaussTria( &num_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &gauss_weights, 2);
    3020 
    3021         /* Start  looping on the number of gaussian points: */
    3022         for (ig=0; ig<num_gauss; ig++){
    3023                 /*Pick up the gaussian point: */
    3024                 gauss_weight=*(gauss_weights+ig);
    3025                 gauss_l1l2l3[0]=*(first_gauss_area_coord+ig);
    3026                 gauss_l1l2l3[1]=*(second_gauss_area_coord+ig);
    3027                 gauss_l1l2l3[2]=*(third_gauss_area_coord+ig);
    3028 
    3029                 /* Get Jacobian determinant: */
    3030                 GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss_l1l2l3);
    3031 
    3032                 /*Get L matrix: */
    3033                 GetL(&L[0], &xyz_list[0][0], gauss_l1l2l3,numberofdofspernode);
    3034 
    3035                 /* Get accumulation, melting and thickness at gauss point */
    3036                 inputs->GetParameterValue(&accumulation_g, &gauss_l1l2l3[0],AccumulationRateEnum);
    3037                 inputs->GetParameterValue(&melting_g, &gauss_l1l2l3[0],MeltingRateEnum);
    3038                 inputs->GetParameterValue(&thickness_g, &gauss_l1l2l3[0],ThicknessEnum);
    3039 
    3040                 /* Add value into pe_g: */
    3041                 for( i=0; i<numdof; i++) pe_g[i]+=Jdettria*gauss_weight*(thickness_g+dt*(accumulation_g-melting_g))*L[i];
    3042 
    3043         } // for (ig=0; ig<num_gauss; ig++)
    3044 
    3045         /*Add pe_g to global matrix Kgg: */
    3046         VecSetValues(pg,numdof,doflist,(const double*)pe_g,ADD_VALUES);
    3047 
    3048 cleanup_and_return:
    3049         xfree((void**)&first_gauss_area_coord);
    3050         xfree((void**)&second_gauss_area_coord);
    3051         xfree((void**)&third_gauss_area_coord);
    3052         xfree((void**)&gauss_weights);
    3053 
    3054 }
    3055 /*}}}*/
    3056 /*FUNCTION Tria::CreatePVectorPrognostic2 {{{1*/
    3057 void  Tria::CreatePVectorPrognostic2(Vec pg){
    3058 
    3059         /* local declarations */
    3060         int             i,j;
    3061 
    3062         /* node data: */
    3063         const int    numgrids=3;
    3064         const int    NDOF1=1;
    3065         const int    numdof=NDOF1*numgrids;
    3066         double       xyz_list[numgrids][3];
    3067         int          doflist[numdof];
    3068         int          numberofdofspernode;
    3069 
    3070         /* gaussian points: */
    3071         int     num_gauss,ig;
    3072         double* first_gauss_area_coord  =  NULL;
    3073         double* second_gauss_area_coord =  NULL;
    3074         double* third_gauss_area_coord  =  NULL;
    3075         double* gauss_weights           =  NULL;
    3076         double  gauss_weight;
    3077         double  gauss_l1l2l3[3];
    3078 
    3079         /* matrix */
    3080         double pe_g[numgrids]={0.0};
    3081         double L[numgrids];
    3082         double Jdettria;
    3083 
    3084         /*input parameters for structural analysis (diagnostic): */
    3085         double  accumulation_g;
    3086         double  melting_g;
    3087         double  thickness_g;
    3088         double  dt;
    3089 
    3090         /*retrieve some parameters: */
    3091         this->parameters->FindParam(&dt,DtEnum);
    3092 
    3093         /* Get node coordinates and dof list: */
    3094         GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
    3095         GetDofList(&doflist[0],&numberofdofspernode);
    3096 
    3097         /* Get gaussian points and weights (make this a statically initialized list of points? fstd): */
    3098         GaussTria( &num_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &gauss_weights, 2);
    3099 
    3100         /* Start  looping on the number of gaussian points: */
    3101         for (ig=0; ig<num_gauss; ig++){
    3102                 /*Pick up the gaussian point: */
    3103                 gauss_weight=*(gauss_weights+ig);
    3104                 gauss_l1l2l3[0]=*(first_gauss_area_coord+ig);
    3105                 gauss_l1l2l3[1]=*(second_gauss_area_coord+ig);
    3106                 gauss_l1l2l3[2]=*(third_gauss_area_coord+ig);
    3107 
    3108                 /* Get Jacobian determinant: */
    3109                 GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss_l1l2l3);
    3110 
    3111                 /*Get L matrix: */
    3112                 GetL(&L[0], &xyz_list[0][0], gauss_l1l2l3,numberofdofspernode);
    3113 
    3114                 /* Get accumulation, melting and thickness at gauss point */
    3115                 inputs->GetParameterValue(&accumulation_g, &gauss_l1l2l3[0],AccumulationRateEnum);
    3116                 inputs->GetParameterValue(&melting_g, &gauss_l1l2l3[0],MeltingRateEnum);
    3117                 inputs->GetParameterValue(&thickness_g, &gauss_l1l2l3[0],ThicknessEnum);
    3118 
    3119                 /* Add value into pe_g: */
    3120                 for( i=0; i<numdof; i++) pe_g[i]+=Jdettria*gauss_weight*(thickness_g+dt*(accumulation_g-melting_g))*L[i];
    3121 
    3122         } // for (ig=0; ig<num_gauss; ig++)
    3123 
    3124         /*Add pe_g to global matrix Kgg: */
    3125         VecSetValues(pg,numdof,doflist,(const double*)pe_g,ADD_VALUES);
    3126 
    3127 cleanup_and_return:
    3128         xfree((void**)&first_gauss_area_coord);
    3129         xfree((void**)&second_gauss_area_coord);
    3130         xfree((void**)&third_gauss_area_coord);
    3131         xfree((void**)&gauss_weights);
    3132 
    3133 }
    3134 /*}}}*/
    3135 /*FUNCTION Tria::CreatePVectorSlopeCompute {{{1*/
    3136 
    3137 void Tria::CreatePVectorSlopeCompute( Vec pg){
    3138 
    3139         int             i,j;
    3140 
    3141         /* node data: */
    3142         const int    numgrids=3;
    3143         const int    NDOF1=1;
    3144         const int    numdof=NDOF1*numgrids;
    3145         double       xyz_list[numgrids][3];
    3146         int          doflist[numdof];
    3147         int          numberofdofspernode;
    3148        
    3149         /* gaussian points: */
    3150         int     num_gauss,ig;
    3151         double* first_gauss_area_coord  =  NULL;
    3152         double* second_gauss_area_coord =  NULL;
    3153         double* third_gauss_area_coord  =  NULL;
    3154         double* gauss_weights           =  NULL;
    3155         double  gauss_weight;
    3156         double  gauss_l1l2l3[3];
    3157 
    3158         /* Jacobian: */
    3159         double Jdet;
    3160 
    3161         /*nodal functions: */
    3162         double l1l2l3[3];
    3163 
    3164         /*element vector at the gaussian points: */
    3165         double  pe_g[numdof]={0.0};
    3166         double  pe_g_gaussian[numdof];
    3167         double  slope[2];
    3168         int sub_analysis_type;
    3169 
    3170         /*retrive parameters: */
    3171         parameters->FindParam(&sub_analysis_type,AnalysisTypeEnum);
    3172 
    3173         /* Get node coordinates and dof list: */
    3174         GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
    3175         GetDofList(&doflist[0],&numberofdofspernode);
    3176 
    3177 
    3178         /* Get gaussian points and weights: */
    3179         GaussTria( &num_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &gauss_weights, 2); /*We need higher order because our load is order 2*/
    3180 
    3181 
    3182         /* Start  looping on the number of gaussian points: */
    3183         for (ig=0; ig<num_gauss; ig++){
    3184                 /*Pick up the gaussian point: */
    3185                 gauss_weight=*(gauss_weights+ig);
    3186                 gauss_l1l2l3[0]=*(first_gauss_area_coord+ig);
    3187                 gauss_l1l2l3[1]=*(second_gauss_area_coord+ig);
    3188                 gauss_l1l2l3[2]=*(third_gauss_area_coord+ig);
    3189 
    3190                 if ( (sub_analysis_type==SurfaceSlopeXAnalysisEnum) || (sub_analysis_type==SurfaceSlopeYAnalysisEnum)){
    3191                         inputs->GetParameterDerivativeValue(&slope[0],&xyz_list[0][0],&gauss_l1l2l3[0],SurfaceEnum);
    3192                 }
    3193                 if ( (sub_analysis_type==BedSlopeXAnalysisEnum) || (sub_analysis_type==BedSlopeYAnalysisEnum)){
    3194                         inputs->GetParameterDerivativeValue(&slope[0],&xyz_list[0][0],&gauss_l1l2l3[0],BedEnum);
    3195                 }
    3196 
    3197                 /* Get Jacobian determinant: */
    3198                 GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0],gauss_l1l2l3);
    3199                
    3200                  /*Get nodal functions: */
    3201                 GetNodalFunctions(l1l2l3, gauss_l1l2l3);
    3202 
    3203                 /*Build pe_g_gaussian vector: */
    3204                 if ( (sub_analysis_type==SurfaceSlopeXAnalysisEnum) || (sub_analysis_type==BedSlopeXAnalysisEnum)){
    3205                         for(i=0;i<numdof;i++) pe_g_gaussian[i]=Jdet*gauss_weight*slope[0]*l1l2l3[i];
    3206                 }
    3207                 if ( (sub_analysis_type==SurfaceSlopeYAnalysisEnum) || (sub_analysis_type==BedSlopeYAnalysisEnum)){
    3208                         for(i=0;i<numdof;i++) pe_g_gaussian[i]=Jdet*gauss_weight*slope[1]*l1l2l3[i];
    3209                 }
    3210 
    3211                 /*Add pe_g_gaussian vector to pe_g: */
    3212                 for( i=0; i<numdof; i++)pe_g[i]+=pe_g_gaussian[i];
    3213 
    3214         } //for (ig=0; ig<num_gauss; ig++)
    3215 
    3216         /*Add pe_g to global vector pg: */
    3217         VecSetValues(pg,numdof,doflist,(const double*)pe_g,ADD_VALUES);
    3218 
    3219         cleanup_and_return:
    3220         xfree((void**)&first_gauss_area_coord);
    3221         xfree((void**)&second_gauss_area_coord);
    3222         xfree((void**)&third_gauss_area_coord);
    3223         xfree((void**)&gauss_weights);
    3224 
    3225 }
    3226 /*}}}*/
    3227 /*FUNCTION Tria::CreatePVectorThermalShelf {{{1*/
    3228 void Tria::CreatePVectorThermalShelf( Vec pg){
    3229 
    3230         int i,found;
    3231        
    3232         const int  numgrids=3;
    3233         const int  NDOF1=1;
    3234         const int  numdof=numgrids*NDOF1;
    3235         int        doflist[numdof];
    3236         int        numberofdofspernode;
    3237         double       xyz_list[numgrids][3];
    3238 
    3239         double mixed_layer_capacity;
    3240         double thermal_exchange_velocity;
    3241         double rho_water;
    3242         double rho_ice;
    3243         double heatcapacity;
    3244         double beta;
    3245         double meltingpoint;
    3246 
    3247         /*inputs: */
    3248         double dt;
    3249         double pressure;
    3250 
    3251         /* gaussian points: */
    3252         int     num_area_gauss,ig;
    3253         double* gauss_weights  =  NULL;
    3254         double* first_gauss_area_coord  =  NULL;
    3255         double* second_gauss_area_coord =  NULL;
    3256         double* third_gauss_area_coord  =  NULL;
    3257         double  gauss_weight;
    3258         double  gauss_coord[3];
    3259         int     dofs1[1]={0};
    3260 
    3261         /*matrices: */
    3262         double  Jdet;
    3263         double  P_terms[numdof]={0.0};
    3264         double  l1l2l3[numgrids];
    3265 
    3266         double  t_pmp;
    3267         double  scalar_ocean;
    3268 
    3269         /* Get node coordinates and dof list: */
    3270         GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
    3271         GetDofList(&doflist[0],&numberofdofspernode);
    3272 
    3273         //recover material parameters
    3274         mixed_layer_capacity=matpar->GetMixedLayerCapacity();
    3275         thermal_exchange_velocity=matpar->GetThermalExchangeVelocity();
    3276         rho_water=matpar->GetRhoWater();
    3277         rho_ice=matpar->GetRhoIce();
    3278         heatcapacity=matpar->GetHeatCapacity();
    3279         beta=matpar->GetBeta();
    3280         meltingpoint=matpar->GetMeltingPoint();
    3281        
    3282         /*retrieve some solution parameters: */
    3283         this->parameters->FindParam(&dt,DtEnum);
    3284 
    3285         /* Ice/ocean heat exchange flux on ice shelf base */
    3286 
    3287         GaussTria (&num_area_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &gauss_weights, 2);
    3288 
    3289         /* Start looping on the number of gauss 2d (nodes on the bedrock) */
    3290         for (ig=0; ig<num_area_gauss; ig++){
    3291                 gauss_weight=*(gauss_weights+ig);
    3292                 gauss_coord[0]=*(first_gauss_area_coord+ig);
    3293                 gauss_coord[1]=*(second_gauss_area_coord+ig);
    3294                 gauss_coord[2]=*(third_gauss_area_coord+ig);
    3295 
    3296                 //Get the Jacobian determinant
    3297                 GetJacobianDeterminant3d(&Jdet, &xyz_list[0][0], gauss_coord);
    3298 
    3299                 /*Get nodal functions values: */
    3300                 GetNodalFunctions(&l1l2l3[0], gauss_coord);
    3301 
    3302                 /*Get geothermal flux and basal friction */
    3303                 inputs->GetParameterValue(&pressure, &gauss_coord[0],PressureEnum);
    3304                 t_pmp=meltingpoint-beta*pressure;
    3305 
    3306                 /*Calculate scalar parameter*/
    3307                 scalar_ocean=gauss_weight*Jdet*rho_water*mixed_layer_capacity*thermal_exchange_velocity*(t_pmp)/(heatcapacity*rho_ice);
    3308                 if(dt){
    3309                         scalar_ocean=dt*scalar_ocean;
    3310                 }
    3311 
    3312                 for(i=0;i<3;i++){
    3313                         P_terms[i]+=scalar_ocean*l1l2l3[i];
    3314                 }
    3315         }
    3316 
    3317         /*Add pe_g to global vector pg: */
    3318         VecSetValues(pg,numdof,doflist,(const double*)P_terms,ADD_VALUES);
    3319 
    3320         cleanup_and_return:
    3321         xfree((void**)&first_gauss_area_coord);
    3322         xfree((void**)&second_gauss_area_coord);
    3323         xfree((void**)&third_gauss_area_coord);
    3324         xfree((void**)&gauss_weights);
    3325 
    3326 }
    3327 /*}}}*/
    3328 /*FUNCTION Tria::CreatePVectorThermalSheet {{{1*/
    3329 void Tria::CreatePVectorThermalSheet( Vec pg){
    3330 
    3331         int i,found;
    3332        
    3333         const int  numgrids=3;
    3334         const int  NDOF1=1;
    3335         const int  numdof=numgrids*NDOF1;
    3336         int        doflist[numdof];
    3337         int        numberofdofspernode;
    3338         double       xyz_list[numgrids][3];
    3339 
    3340         double rho_ice;
    3341         double heatcapacity;
    3342 
    3343         /*inputs: */
    3344         double dt;
    3345         double pressure_list[3];
    3346         double pressure;
    3347         int    drag_type;
    3348         double basalfriction;
    3349         Friction* friction=NULL;
    3350         double alpha2,vx,vy;
    3351         double geothermalflux_value;
    3352 
    3353         /* gaussian points: */
    3354         int     num_area_gauss,ig;
    3355         double* gauss_weights  =  NULL;
    3356         double* first_gauss_area_coord  =  NULL;
    3357         double* second_gauss_area_coord =  NULL;
    3358         double* third_gauss_area_coord  =  NULL;
    3359         double  gauss_weight;
    3360         double  gauss_coord[3];
    3361 
    3362         /*matrices: */
    3363         double  Jdet;
    3364         double  P_terms[numdof]={0.0};
    3365         double  l1l2l3[numgrids];
    3366         double  scalar;
    3367 
    3368         int analysis_type;
    3369 
    3370         /*retrive parameters: */
    3371         parameters->FindParam(&analysis_type,AnalysisTypeEnum);
    3372 
    3373        
    3374         /* Get node coordinates and dof list: */
    3375         GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
    3376         GetDofList(&doflist[0],&numberofdofspernode);
    3377 
    3378         //recover material parameters
    3379         rho_ice=matpar->GetRhoIce();
    3380         heatcapacity=matpar->GetHeatCapacity();
    3381 
    3382         /*retrieve some parameters: */
    3383         this->parameters->FindParam(&dt,DtEnum);
    3384 
    3385         /*Build frictoin element, needed later: */
    3386         inputs->GetParameterValue(&drag_type,DragTypeEnum);
    3387         if (drag_type!=2)ISSMERROR(" non-viscous friction not supported yet!");
    3388         friction=new Friction("3d",inputs,matpar,analysis_type);
    3389        
    3390         /* Ice/ocean heat exchange flux on ice shelf base */
    3391         GaussTria (&num_area_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &gauss_weights, 2);
    3392 
    3393         /* Start looping on the number of gauss 2d (nodes on the bedrock) */
    3394         for (ig=0; ig<num_area_gauss; ig++){
    3395                 gauss_weight=*(gauss_weights+ig);
    3396                 gauss_coord[0]=*(first_gauss_area_coord+ig);
    3397                 gauss_coord[1]=*(second_gauss_area_coord+ig);
    3398                 gauss_coord[2]=*(third_gauss_area_coord+ig);
    3399 
    3400                 //Get the Jacobian determinant
    3401                 GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0], gauss_coord);
    3402 
    3403                 /*Get nodal functions values: */
    3404                 GetNodalFunctions(&l1l2l3[0], gauss_coord);
    3405 
    3406                 /*Get geothermal flux and basal friction */
    3407                 inputs->GetParameterValue(&geothermalflux_value, &gauss_coord[0],GeothermalFluxEnum);
    3408        
    3409                 friction->GetAlpha2(&alpha2,&gauss_coord[0],VxEnum,VyEnum,VzEnum);
    3410                 inputs->GetParameterValue(&vx, &gauss_coord[0],VxEnum);
    3411                 inputs->GetParameterValue(&vy, &gauss_coord[0],VyEnum);
    3412                 basalfriction= alpha2*(pow(vx,(double)2.0)+pow(vy,(double)2.0));
    3413                
    3414                 /*Calculate scalar parameter*/
    3415                 scalar=gauss_weight*Jdet*(basalfriction+geothermalflux_value)/(heatcapacity*rho_ice);
    3416                 if(dt){
    3417                         scalar=dt*scalar;
    3418                 }
    3419 
    3420                 for(i=0;i<3;i++){
    3421                         P_terms[i]+=scalar*l1l2l3[i];
    3422                 }
    3423         }
    3424 
    3425         /*Add pe_g to global vector pg: */
    3426         VecSetValues(pg,numdof,doflist,(const double*)P_terms,ADD_VALUES);
    3427 
    3428         cleanup_and_return:
    3429         xfree((void**)&first_gauss_area_coord);
    3430         xfree((void**)&second_gauss_area_coord);
    3431         xfree((void**)&third_gauss_area_coord);
    3432         xfree((void**)&gauss_weights);
    3433         delete friction;
    3434669
    3435670}
     
    3674909}
    3675910/*}}}*/
    3676 /*FUNCTION Tria::GetArea {{{1*/
    3677 double Tria::GetArea(void){
    3678 
    3679         double area=0;
    3680         const int    numgrids=3;
    3681         double xyz_list[numgrids][3];
    3682         double x1,y1,x2,y2,x3,y3;
    3683 
    3684         /*Get xyz list: */
    3685         GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
    3686         x1=xyz_list[0][0]; y1=xyz_list[0][1];
    3687         x2=xyz_list[1][0]; y2=xyz_list[1][1];
    3688         x3=xyz_list[2][0]; y3=xyz_list[2][1];
    3689  
    3690         return x2*y3 - y2*x3 + x1*y2 - y1*x2 + x3*y1 - y3*x1;
    3691 }
    3692 /*}}}*/
    3693 /*FUNCTION Tria::GetAreaCoordinate {{{1*/
    3694 double Tria::GetAreaCoordinate(double x, double y, int which_one){
    3695 
    3696         double area=0;
    3697         const int    numgrids=3;
    3698         double xyz_list[numgrids][3];
    3699         double x1,y1,x2,y2,x3,y3;
    3700 
    3701         /*Get area: */
    3702         area=this->GetArea();
    3703 
    3704         /*Get xyz list: */
    3705         GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
    3706         x1=xyz_list[0][0]; y1=xyz_list[0][1];
    3707         x2=xyz_list[1][0]; y2=xyz_list[1][1];
    3708         x3=xyz_list[2][0]; y3=xyz_list[2][1];
    3709 
    3710         if(which_one==1){
    3711                 /*Get first area coordinate = det(x-x3  x2-x3 ; y-y3   y2-y3)/area*/
    3712                 return ((x-x3)*(y2-y3)-(x2-x3)*(y-y3))/area;
    3713         }
    3714         else if(which_one==2){
    3715                 /*Get second area coordinate = det(x1-x3  x-x3 ; y1-y3   y-y3)/area*/
    3716                 return ((x1-x3)*(y-y3)-(x-x3)*(y1-y3))/area;
    3717         }
    3718         else if(which_one==3){
    3719                 /*Get third  area coordinate 1-area1-area2: */
    3720                 return 1-((x-x3)*(y2-y3)-(x2-x3)*(y-y3))/area -((x1-x3)*(y-y3)-(x-x3)*(y1-y3))/area;
    3721         }
    3722         else ISSMERROR("%s%i%s\n"," error message: area coordinate ",which_one," done not exist!");
    3723 }
    3724 /*}}}*/
    3725 /*FUNCTION Tria::GetB {{{1*/
    3726 
    3727 void Tria::GetB(double* B, double* xyz_list, double* gauss_l1l2l3){
    3728 
    3729         /*Compute B  matrix. B=[B1 B2 B3] where Bi is of size 3*NDOF2.
    3730          * For grid i, Bi can be expressed in the actual coordinate system
    3731          * by:
    3732          *       Bi=[ dh/dx    0    ]
    3733          *                [   0    dh/dy  ]
    3734          *                [ 1/2*dh/dy  1/2*dh/dx  ]
    3735          * where h is the interpolation function for grid i.
    3736          *
    3737          * We assume B has been allocated already, of size: 3x(NDOF2*numgrids)
    3738          */
    3739        
    3740         int i;
    3741         const int NDOF2=2;
    3742         const int numgrids=3;
    3743 
    3744         double dh1dh3[NDOF2][numgrids];
    3745 
    3746 
    3747         /*Get dh1dh2dh3 in actual coordinate system: */
    3748         GetNodalFunctionsDerivatives(&dh1dh3[0][0],xyz_list, gauss_l1l2l3);
    3749 
    3750         /*Build B: */
    3751         for (i=0;i<numgrids;i++){
    3752                 *(B+NDOF2*numgrids*0+NDOF2*i)=dh1dh3[0][i]; //B[0][NDOF2*i]=dh1dh3[0][i];
    3753                 *(B+NDOF2*numgrids*0+NDOF2*i+1)=0;
    3754                 *(B+NDOF2*numgrids*1+NDOF2*i)=0;
    3755                 *(B+NDOF2*numgrids*1+NDOF2*i+1)=dh1dh3[1][i];
    3756                 *(B+NDOF2*numgrids*2+NDOF2*i)=(float).5*dh1dh3[1][i];
    3757                 *(B+NDOF2*numgrids*2+NDOF2*i+1)=(float).5*dh1dh3[0][i];
    3758         }
    3759 }
    3760 /*}}}*/
    3761 /*FUNCTION Tria::GetB_prog {{{1*/
    3762 
    3763 void Tria::GetB_prog(double* B_prog, double* xyz_list, double* gauss_l1l2l3){
    3764 
    3765         /*Compute B  matrix. B=[B1 B2 B3] where Bi is of size 3*NDOF2.
    3766          * For grid i, Bi can be expressed in the actual coordinate system
    3767          * by:
    3768          *       Bi=[ h ]
    3769          *                [ h ]
    3770          * where h is the interpolation function for grid i.
    3771          *
    3772          * We assume B_prog has been allocated already, of size: 2x(NDOF1*numgrids)
    3773          */
    3774 
    3775         int i;
    3776         const int NDOF1=1;
    3777         const int numgrids=3;
    3778 
    3779         double l1l2l3[numgrids];
    3780 
    3781 
    3782         /*Get dh1dh2dh3 in actual coordinate system: */
    3783         GetNodalFunctions(&l1l2l3[0],gauss_l1l2l3);
    3784 
    3785         /*Build B_prog: */
    3786         for (i=0;i<numgrids;i++){
    3787                 *(B_prog+NDOF1*numgrids*0+NDOF1*i)=l1l2l3[i];
    3788                 *(B_prog+NDOF1*numgrids*1+NDOF1*i)=l1l2l3[i];
    3789         }
    3790 }
    3791 /*}}}*/
    3792911/*FUNCTION Tria::GetBedList {{{1*/
    3793912void  Tria::GetBedList(double* bedlist){
     
    3800919}
    3801920/*}}}*/
    3802 /*FUNCTION Tria::GetBPrime {{{1*/
    3803 
    3804 void Tria::GetBPrime(double* Bprime, double* xyz_list, double* gauss_l1l2l3){
    3805 
    3806         /*Compute B'  matrix. B'=[B1' B2' B3'] where Bi' is of size 3*NDOF2.
    3807          * For grid i, Bi' can be expressed in the actual coordinate system
    3808          * by:
    3809          *       Bi_prime=[ 2*dh/dx dh/dy ]
    3810          *                       [ dh/dx  2*dh/dy]
    3811          *                       [dh/dy dh/dx]
    3812          * where h is the interpolation function for grid i.
    3813          *
    3814          * We assume B' has been allocated already, of size: 3x(NDOF2*numgrids)
    3815          */
    3816        
    3817         int i;
    3818         const int NDOF2=2;
    3819         const int numgrids=3;
    3820 
    3821         /*Same thing in the actual coordinate system: */
    3822         double dh1dh3[NDOF2][numgrids];
    3823 
    3824 
    3825         /*Get dh1dh2dh3 in actual coordinates system : */
    3826         GetNodalFunctionsDerivatives(&dh1dh3[0][0],xyz_list,gauss_l1l2l3);
    3827 
    3828         /*Build B': */
    3829         for (i=0;i<numgrids;i++){
    3830                 *(Bprime+NDOF2*numgrids*0+NDOF2*i)=2*dh1dh3[0][i];
    3831                 *(Bprime+NDOF2*numgrids*0+NDOF2*i+1)=dh1dh3[1][i];
    3832                 *(Bprime+NDOF2*numgrids*1+NDOF2*i)=dh1dh3[0][i];
    3833                 *(Bprime+NDOF2*numgrids*1+NDOF2*i+1)=2*dh1dh3[1][i];
    3834                 *(Bprime+NDOF2*numgrids*2+NDOF2*i)=dh1dh3[1][i];
    3835                 *(Bprime+NDOF2*numgrids*2+NDOF2*i+1)=dh1dh3[0][i];
    3836         }
    3837 }
    3838 /*}}}*/
    3839 /*FUNCTION Tria::GetBPrime_prog {{{1*/
    3840 
    3841 void Tria::GetBPrime_prog(double* Bprime_prog, double* xyz_list, double* gauss_l1l2l3){
    3842 
    3843         /*Compute B'  matrix. B'=[B1' B2' B3'] where Bi' is of size 3*NDOF2.
    3844          * For grid i, Bi' can be expressed in the actual coordinate system
    3845          * by:
    3846          *       Bi_prime=[ dh/dx ]
    3847          *                       [ dh/dy ]
    3848          * where h is the interpolation function for grid i.
    3849          *
    3850          * We assume B' has been allocated already, of size: 3x(NDOF2*numgrids)
    3851          */
    3852 
    3853         int i;
    3854         const int NDOF1=1;
    3855         const int NDOF2=2;
    3856         const int numgrids=3;
    3857 
    3858         /*Same thing in the actual coordinate system: */
    3859         double dh1dh3[NDOF2][numgrids];
    3860 
    3861         /*Get dh1dh2dh3 in actual coordinates system : */
    3862         GetNodalFunctionsDerivatives(&dh1dh3[0][0],xyz_list,gauss_l1l2l3);
    3863 
    3864         /*Build B': */
    3865         for (i=0;i<numgrids;i++){
    3866                 *(Bprime_prog+NDOF1*numgrids*0+NDOF1*i)=dh1dh3[0][i];
    3867                 *(Bprime_prog+NDOF1*numgrids*1+NDOF1*i)=dh1dh3[1][i];
    3868         }
    3869 }
    3870 /*}}}*/
    3871 /*FUNCTION Tria::GetDofList {{{1*/
    3872 void  Tria::GetDofList(int* doflist,int* pnumberofdofspernode){
    3873 
    3874         int i,j;
    3875         int doflist_per_node[MAXDOFSPERNODE];
    3876         int numberofdofspernode;
    3877 
    3878         /*Some checks for debugging*/
    3879         ISSMASSERT(doflist);
    3880         ISSMASSERT(pnumberofdofspernode);
    3881         ISSMASSERT(nodes);
    3882 
    3883         /*Build doflist from nodes*/
    3884         for(i=0;i<3;i++){
    3885                 nodes[i]->GetDofList(&doflist_per_node[0],&numberofdofspernode);
    3886                 for(j=0;j<numberofdofspernode;j++){
    3887                         doflist[i*numberofdofspernode+j]=doflist_per_node[j];
    3888                 }
    3889         }
    3890 
    3891         /*Assign output pointers:*/
    3892         *pnumberofdofspernode=numberofdofspernode;
    3893 
    3894 }
    3895 /*}}}*/
    3896 /*FUNCTION Tria::GetDofList1 {{{1*/
    3897 void  Tria::GetDofList1(int* doflist){
    3898 
    3899         int i;
    3900         for(i=0;i<3;i++){
    3901                 doflist[i]=nodes[i]->GetDofList1();
    3902         }
    3903 
    3904 }
    3905 /*}}}*/
    3906 /*FUNCTION Tria::GetJacobian {{{1*/
    3907 void Tria::GetJacobian(double* J, double* xyz_list,double* gauss_l1l2l3){
    3908 
    3909         /*The Jacobian is constant over the element, discard the gaussian points.
    3910          * J is assumed to have been allocated of size NDOF2xNDOF2.*/
    3911 
    3912         const int NDOF2=2;
    3913         const int numgrids=3;
    3914         double x1,y1,x2,y2,x3,y3;
    3915        
    3916         x1=*(xyz_list+numgrids*0+0);
    3917         y1=*(xyz_list+numgrids*0+1);
    3918         x2=*(xyz_list+numgrids*1+0);
    3919         y2=*(xyz_list+numgrids*1+1);
    3920         x3=*(xyz_list+numgrids*2+0);
    3921         y3=*(xyz_list+numgrids*2+1);
    3922 
    3923 
    3924         *(J+NDOF2*0+0)=0.5*(x2-x1);
    3925         *(J+NDOF2*1+0)=SQRT3/6.0*(2*x3-x1-x2);
    3926         *(J+NDOF2*0+1)=0.5*(y2-y1);
    3927         *(J+NDOF2*1+1)=SQRT3/6.0*(2*y3-y1-y2);
    3928 }
    3929 /*}}}*/
    3930 /*FUNCTION Tria::GetJacobianDeterminant2d {{{1*/
    3931 void Tria::GetJacobianDeterminant2d(double*  Jdet, double* xyz_list,double* gauss_l1l2l3){
    3932 
    3933         /*The Jacobian determinant is constant over the element, discard the gaussian points.
    3934          * J is assumed to have been allocated of size NDOF2xNDOF2.*/
    3935 
    3936         double x1,x2,x3,y1,y2,y3;
    3937        
    3938         x1=*(xyz_list+3*0+0);
    3939         y1=*(xyz_list+3*0+1);
    3940         x2=*(xyz_list+3*1+0);
    3941         y2=*(xyz_list+3*1+1);
    3942         x3=*(xyz_list+3*2+0);
    3943         y3=*(xyz_list+3*2+1);
    3944 
    3945 
    3946         *Jdet=SQRT3/6.0*((x2-x1)*(y3-y1)-(y2-y1)*(x3-x1));
    3947 
    3948 
    3949         if(Jdet<0){
    3950                 ISSMERROR("negative jacobian determinant!");
    3951         }
    3952        
    3953 }
    3954 /*}}}*/
    3955 /*FUNCTION Tria::GetJacobianDeterminant3d {{{1*/
    3956 void Tria::GetJacobianDeterminant3d(double*  Jdet, double* xyz_list,double* gauss_l1l2l3){
    3957 
    3958         /*The Jacobian determinant is constant over the element, discard the gaussian points.
    3959          * J is assumed to have been allocated of size NDOF2xNDOF2.*/
    3960 
    3961         double x1,x2,x3,y1,y2,y3,z1,z2,z3;
    3962        
    3963         x1=*(xyz_list+3*0+0);
    3964         y1=*(xyz_list+3*0+1);
    3965         z1=*(xyz_list+3*0+2);
    3966         x2=*(xyz_list+3*1+0);
    3967         y2=*(xyz_list+3*1+1);
    3968         z2=*(xyz_list+3*1+2);
    3969         x3=*(xyz_list+3*2+0);
    3970         y3=*(xyz_list+3*2+1);
    3971         z3=*(xyz_list+3*2+2);
    3972 
    3973 
    3974         *Jdet=SQRT3/6.0*pow(pow(((y2-y1)*(z3-z1)-(z2-z1)*(y3-y1)),2.0)+pow(((z2-z1)*(x3-x1)-(x2-x1)*(z3-z1)),2.0)+pow(((x2-x1)*(y3-y1)-(y2-y1)*(x3-x1)),2.0),0.5);
    3975 
    3976         if(Jdet<0){
    3977                 ISSMERROR("negative jacobian determinant!");
    3978         }
    3979        
    3980 }
    3981 /*}}}*/
    3982 /*FUNCTION Tria::GetJacobianInvert {{{1*/
    3983 void Tria::GetJacobianInvert(double*  Jinv, double* xyz_list,double* gauss_l1l2l3){
    3984 
    3985         double Jdet;
    3986         const int NDOF2=2;
    3987         const int numgrids=3;
    3988 
    3989         /*Call Jacobian routine to get the jacobian:*/
    3990         GetJacobian(Jinv, xyz_list, gauss_l1l2l3);
    3991 
    3992         /*Invert Jacobian matrix: */
    3993         MatrixInverse(Jinv,NDOF2,NDOF2,NULL,0,&Jdet);
    3994 
    3995 }
    3996 /*}}}*/
    3997 /*FUNCTION Tria::GetL {{{1*/
    3998 
    3999 void Tria::GetL(double* L, double* xyz_list, double* gauss_l1l2l3,int numdof){
    4000 
    4001         /*Compute L  matrix. L=[L1 L2 L3] where Li is square and of size numdof.
    4002          * For grid i, Li can be expressed in the actual coordinate system
    4003          * by:
    4004          *       numdof=1:
    4005          *       Li=h;
    4006          *       numdof=2:
    4007          *       Li=[ h    0    ]
    4008          *                [   0   h  ]
    4009          * where h is the interpolation function for grid i.
    4010          *
    4011          * We assume L has been allocated already, of size: numgrids (numdof=1), or numdofx(numdof*numgrids) (numdof=2)
    4012          */
    4013 
    4014         int i;
    4015         const int NDOF2=2;
    4016         const int numgrids=3;
    4017 
    4018         double l1l2l3[3];
    4019 
    4020 
    4021         /*Get l1l2l3 in actual coordinate system: */
    4022         GetNodalFunctions(l1l2l3, gauss_l1l2l3);
    4023 
    4024 #ifdef _DELUG_
    4025         for (i=0;i<3;i++){
    4026                 printf("Node %i  h=%lf \n",i,l1l2l3[i]);
    4027         }
    4028 #endif
    4029 
    4030         /*Build L: */
    4031         if(numdof==1){
    4032                 for (i=0;i<numgrids;i++){
    4033                         L[i]=l1l2l3[i];
    4034                 }
    4035         }
    4036         else{
    4037                 for (i=0;i<numgrids;i++){
    4038                         *(L+numdof*numgrids*0+numdof*i)=l1l2l3[i]; //L[0][NDOF2*i]=dh1dh3[0][i];
    4039                         *(L+numdof*numgrids*0+numdof*i+1)=0;
    4040                         *(L+numdof*numgrids*1+numdof*i)=0;
    4041                         *(L+numdof*numgrids*1+numdof*i+1)=l1l2l3[i];
    4042                 }
    4043         }
    4044 }
    4045 /*}}}*/
    4046921/*FUNCTION Tria::GetMatPar {{{1*/
    4047922void* Tria::GetMatPar(){
    4048923
    4049924        return matpar;
    4050 }
    4051 /*}}}*/
    4052 /*FUNCTION Tria::GetNodalFunctions {{{1*/
    4053 void Tria::GetNodalFunctions(double* l1l2l3, double* gauss_l1l2l3){
    4054        
    4055         /*This routine returns the values of the nodal functions  at the gaussian point.*/
    4056 
    4057         /*First nodal function: */
    4058         l1l2l3[0]=gauss_l1l2l3[0];
    4059 
    4060         /*Second nodal function: */
    4061         l1l2l3[1]=gauss_l1l2l3[1];
    4062 
    4063         /*Third nodal function: */
    4064         l1l2l3[2]=gauss_l1l2l3[2];
    4065 
    4066 }
    4067 /*}}}*/
    4068 /*FUNCTION Tria::GetNodalFunctionsDerivatives {{{1*/
    4069 void Tria::GetNodalFunctionsDerivatives(double* dh1dh3,double* xyz_list, double* gauss_l1l2l3){
    4070        
    4071         /*This routine returns the values of the nodal functions derivatives  (with respect to the
    4072          * actual coordinate system: */
    4073 
    4074         int i;
    4075         const int NDOF2=2;
    4076         const int numgrids=3;
    4077 
    4078         double dh1dh3_ref[NDOF2][numgrids];
    4079         double Jinv[NDOF2][NDOF2];
    4080 
    4081 
    4082         /*Get derivative values with respect to parametric coordinate system: */
    4083         GetNodalFunctionsDerivativesReference(&dh1dh3_ref[0][0], gauss_l1l2l3);
    4084 
    4085         /*Get Jacobian invert: */
    4086         GetJacobianInvert(&Jinv[0][0], xyz_list, gauss_l1l2l3);
    4087 
    4088         /*Build dh1dh3:
    4089          *
    4090          * [dhi/dx]= Jinv*[dhi/dr]
    4091          * [dhi/dy]       [dhi/ds]
    4092          */
    4093 
    4094         for (i=0;i<numgrids;i++){
    4095                 *(dh1dh3+numgrids*0+i)=Jinv[0][0]*dh1dh3_ref[0][i]+Jinv[0][1]*dh1dh3_ref[1][i];
    4096                 *(dh1dh3+numgrids*1+i)=Jinv[1][0]*dh1dh3_ref[0][i]+Jinv[1][1]*dh1dh3_ref[1][i];
    4097         }
    4098 
    4099 }
    4100 /*}}}*/
    4101 /*FUNCTION Tria::GetNodalFunctionsDerivativesReference {{{1*/
    4102 void Tria::GetNodalFunctionsDerivativesReference(double* dl1dl3,double* gauss_l1l2l3){
    4103        
    4104         /*This routine returns the values of the nodal functions derivatives  (with respect to the
    4105          * natural coordinate system) at the gaussian point. */
    4106 
    4107         const int NDOF2=2;
    4108         const int numgrids=3;
    4109 
    4110         /*First nodal function: */
    4111         *(dl1dl3+numgrids*0+0)=-0.5;
    4112         *(dl1dl3+numgrids*1+0)=-1.0/(2.0*SQRT3);
    4113 
    4114         /*Second nodal function: */
    4115         *(dl1dl3+numgrids*0+1)=0.5;
    4116         *(dl1dl3+numgrids*1+1)=-1.0/(2.0*SQRT3);
    4117 
    4118         /*Third nodal function: */
    4119         *(dl1dl3+numgrids*0+2)=0;
    4120         *(dl1dl3+numgrids*1+2)=1.0/SQRT3;
    4121 
    4122925}
    4123926/*}}}*/
     
    4144947}
    4145948/*}}}*/
    4146 /*FUNCTION Tria::GetParameterDerivativeValue {{{1*/
    4147 void Tria::GetParameterDerivativeValue(double* p, double* plist,double* xyz_list, double* gauss_l1l2l3){
    4148          
    4149         const int NDOF2=2;
    4150         const int numgrids=3;
    4151         /*From node values of parameter p (plist[0],plist[1],plist[2]), return parameter derivative value at gaussian
    4152          * point specified by gauss_l1l2l3:
    4153          *   dp/dx=plist[0]*dh1/dx+plist[1]*dh2/dx+plist[2]*dh3/dx
    4154          *   dp/dx=plist[0]*dh1/dx+plist[1]*dh2/dx+plist[2]*dh3/dx
    4155          *
    4156          * p is a vector of size 2x1 already allocated.
    4157          */
    4158        
    4159         double dh1dh3[NDOF2][numgrids]; //nodal derivative functions in actual coordinate system.
    4160 
    4161         /*Get dh1dh2dh3 in actual coordinate system: */
    4162         GetNodalFunctionsDerivatives(&dh1dh3[0][0],xyz_list, gauss_l1l2l3);
    4163 
    4164         *(p+0)=plist[0]*dh1dh3[0][0]+plist[1]*dh1dh3[0][1]+plist[2]*dh1dh3[0][2];
    4165         *(p+1)=plist[0]*dh1dh3[1][0]+plist[1]*dh1dh3[1][1]+plist[2]*dh1dh3[1][2];
    4166 
    4167 }
    4168 /*}}}*/
    4169 /*FUNCTION Tria::GetParameterValue {{{1*/
    4170 void Tria::GetParameterValue(double* pp, double* plist, double* gauss_l1l2l3){
    4171        
    4172         /*From node values of parameter p (plist[0],plist[1],plist[2]), return parameter value at gaussian
    4173          * point specifie by gauss_l1l2l3: */
    4174        
    4175         /*nodal functions: */
    4176         double l1l2l3[3];
    4177 
    4178         /*output: */
    4179         double p;
    4180 
    4181         GetNodalFunctions(l1l2l3, gauss_l1l2l3);
    4182 
    4183         p=l1l2l3[0]*plist[0]+l1l2l3[1]*plist[1]+l1l2l3[2]*plist[2];
    4184 
    4185         /*Assign output pointers:*/
    4186         *pp=p;
    4187 }
    4188 /*}}}*/
    4189949/*FUNCTION Tria::GetShelf {{{1*/
    4190950bool   Tria::GetShelf(){
     
    4198958}
    4199959/*}}}*/
     960/*FUNCTION Tria::GetSolutionFromInputs(Vec solution){{{1*/
     961void  Tria::GetSolutionFromInputs(Vec solution){
     962
     963        int analysis_type;
     964
     965        /*retrive parameters: */
     966        parameters->FindParam(&analysis_type,AnalysisTypeEnum);
     967       
     968        /*Just branch to the correct InputUpdateFromSolution generator, according to the type of analysis we are carrying out: */
     969        if (analysis_type==DiagnosticHorizAnalysisEnum)
     970                GetSolutionFromInputsDiagnosticHoriz(solution);
     971        else
     972         ISSMERROR("%s%i%s\n","analysis: ",analysis_type," not supported yet");
     973
     974}
     975/*}}}*/
    4200976/*FUNCTION Tria::GetThicknessList {{{1*/
    4201977void Tria::GetThicknessList(double* thickness_list){
     
    4207983}
    4208984/*}}}*/
     985/*FUNCTION Tria::GetVectorFromInputs(Vec vector,int NameEnum){{{1*/
     986void  Tria::GetVectorFromInputs(Vec vector,int NameEnum){
     987
     988        int i;
     989        const int numvertices=3;
     990        int doflist1[numvertices];
     991
     992        /*Find NameEnum input in the inputs dataset, and get it to fill in the vector: */
     993        for(i=0;i<this->inputs->Size();i++){
     994                Input* input=(Input*)this->inputs->GetObjectByOffset(i);
     995                if(input->EnumType()==NameEnum){
     996                        /*We found the enum.  Use its values to fill into the vector, using the vertices ids: */
     997                        this->GetDofList1(&doflist1[0]);
     998                        input->GetVectorFromInputs(vector,&doflist1[0]);
     999                        break;
     1000                }
     1001        }
     1002}
     1003/*}}}*/
    42091004/*FUNCTION Tria::Gradj {{{1*/
    42101005void  Tria::Gradj(Vec gradient,int control_type){
     
    42261021        }
    42271022        else ISSMERROR("%s%i","control type not supported yet: ",control_type);
    4228 }
    4229 /*}}}*/
    4230 /*FUNCTION Tria::GradjDrag {{{1*/
    4231 void  Tria::GradjDrag(Vec gradient){
    4232 
    4233 
    4234         int i;
    4235 
    4236         /* node data: */
    4237         const int    numgrids=3;
    4238         const int    NDOF2=2;
    4239         const int    numdof=NDOF2*numgrids;
    4240         double       xyz_list[numgrids][3];
    4241         int          doflist1[numgrids];
    4242         double       dh1dh3[NDOF2][numgrids];
    4243 
    4244         /* grid data: */
    4245         double adjx_list[numgrids];
    4246         double adjy_list[numgrids];
    4247 
    4248         /* gaussian points: */
    4249         int     num_gauss,ig;
    4250         double* first_gauss_area_coord  =  NULL;
    4251         double* second_gauss_area_coord =  NULL;
    4252         double* third_gauss_area_coord  =  NULL;
    4253         double* gauss_weights           =  NULL;
    4254         double  gauss_weight;
    4255         double  gauss_l1l2l3[3];
    4256 
    4257         /* parameters: */
    4258         double  dk[NDOF2];
    4259         double  vx,vy;
    4260         double  lambda,mu;
    4261         double  bed,thickness,Neff;
    4262         double  alpha_complement;
    4263         int     drag_type;
    4264         double  drag;
    4265         Friction* friction=NULL;
    4266 
    4267         /*element vector at the gaussian points: */
    4268         double  grade_g[numgrids]={0.0};
    4269         double  grade_g_gaussian[numgrids];
    4270 
    4271         /* Jacobian: */
    4272         double Jdet;
    4273 
    4274         /*nodal functions: */
    4275         double l1l2l3[3];
    4276 
    4277         /* strain rate: */
    4278         double epsilon[3]; /* epsilon=[exx,eyy,exy];*/
    4279 
    4280         /*inputs: */
    4281         bool shelf;
    4282 
    4283         /*parameters: */
    4284         double  cm_noisedmp;
    4285         double  cm_mindmp_slope;
    4286         double  cm_mindmp_value;
    4287         double  cm_maxdmp_value;
    4288         double  cm_maxdmp_slope;
    4289 
    4290         int analysis_type;
    4291 
    4292         /*retrive parameters: */
    4293         parameters->FindParam(&analysis_type,AnalysisTypeEnum);
    4294 
    4295         /*retrieve inputs :*/
    4296         inputs->GetParameterValue(&shelf,ElementOnIceShelfEnum);
    4297 
    4298         /*retrieve some parameters: */
    4299         this->parameters->FindParam(&cm_noisedmp,CmNoiseDmpEnum);
    4300         this->parameters->FindParam(&cm_mindmp_value,CmMinDmpValueEnum);
    4301         this->parameters->FindParam(&cm_mindmp_slope,CmMinDmpSlopeEnum);
    4302         this->parameters->FindParam(&cm_maxdmp_value,CmMaxDmpValueEnum);
    4303         this->parameters->FindParam(&cm_maxdmp_slope,CmMaxDmpSlopeEnum);
    4304 
    4305 
    4306         /*Get out if shelf*/
    4307         if(shelf)return;
    4308 
    4309         /* Get node coordinates and dof list: */
    4310         GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
    4311         GetDofList1(&doflist1[0]);
    4312 
    4313         /*Build frictoin element, needed later: */
    4314         inputs->GetParameterValue(&drag_type,DragTypeEnum);
    4315         friction=new Friction("2d",inputs,matpar,analysis_type);
    4316 
    4317         /* Get gaussian points and weights (make this a statically initialized list of points? fstd): */
    4318         GaussTria( &num_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &gauss_weights, 4);
    4319 
    4320         /* Start  looping on the number of gaussian points: */
    4321         for (ig=0; ig<num_gauss; ig++){
    4322                 /*Pick up the gaussian point: */
    4323                 gauss_weight=*(gauss_weights+ig);
    4324                 gauss_l1l2l3[0]=*(first_gauss_area_coord+ig);
    4325                 gauss_l1l2l3[1]=*(second_gauss_area_coord+ig);
    4326                 gauss_l1l2l3[2]=*(third_gauss_area_coord+ig);
    4327 
    4328                 /*Build alpha_complement_list: */
    4329                 if (drag_type==2) friction->GetAlphaComplement(&alpha_complement, gauss_l1l2l3,VxAverageEnum,VyAverageEnum);
    4330                 else alpha_complement=0;
    4331        
    4332                 /*Recover alpha_complement and k: */
    4333                 inputs->GetParameterValue(&drag, gauss_l1l2l3,DragCoefficientEnum);
    4334 
    4335                 /*recover lambda and mu: */
    4336                 inputs->GetParameterValue(&lambda, gauss_l1l2l3,AdjointxEnum);
    4337                 inputs->GetParameterValue(&mu, gauss_l1l2l3,AdjointyEnum);
    4338                        
    4339                 /*recover vx and vy: */
    4340                 inputs->GetParameterValue(&vx, gauss_l1l2l3,VxEnum);
    4341                 inputs->GetParameterValue(&vy, gauss_l1l2l3,VyEnum);
    4342 
    4343                 /* Get Jacobian determinant: */
    4344                 GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0],gauss_l1l2l3);
    4345                
    4346                 /* Get nodal functions value at gaussian point:*/
    4347                 GetNodalFunctions(l1l2l3, gauss_l1l2l3);
    4348 
    4349                 /*Get nodal functions derivatives*/
    4350                 GetNodalFunctionsDerivatives(&dh1dh3[0][0],&xyz_list[0][0],gauss_l1l2l3);
    4351 
    4352                 /*Get k derivative: dk/dx */
    4353                 inputs->GetParameterDerivativeValue(&dk[0],&xyz_list[0][0],&gauss_l1l2l3[0],DragCoefficientEnum);
    4354 
    4355                 /*Build gradje_g_gaussian vector (actually -dJ/ddrag): */
    4356                 for (i=0;i<numgrids;i++){
    4357 
    4358                         //standard term dJ/dki
    4359                         grade_g_gaussian[i]=-2*drag*alpha_complement*((lambda*vx+mu*vy))*Jdet*gauss_weight*l1l2l3[i];
    4360 
    4361                         //noise dampening d/dki(1/2*(dk/dx)^2)
    4362                         grade_g_gaussian[i]+=-cm_noisedmp*Jdet*gauss_weight*(dh1dh3[0][i]*dk[0]+dh1dh3[1][i]*dk[1]);
    4363                        
    4364                         //min dampening
    4365                         if(drag<cm_mindmp_value){
    4366                                 grade_g_gaussian[i]+=cm_mindmp_slope*Jdet*gauss_weight*l1l2l3[i];
    4367                         }
    4368 
    4369                         //max dampening
    4370                         if(drag>cm_maxdmp_value){
    4371                                 grade_g_gaussian[i]+= - cm_maxdmp_slope*Jdet*gauss_weight*l1l2l3[i];
    4372                         }
    4373                 }
    4374                
    4375                 /*Add gradje_g_gaussian vector to gradje_g: */
    4376                 for( i=0; i<numgrids; i++)grade_g[i]+=grade_g_gaussian[i];
    4377         }
    4378 
    4379 
    4380         /*Add grade_g to global vector gradient: */
    4381         VecSetValues(gradient,numgrids,doflist1,(const double*)grade_g,ADD_VALUES);
    4382 
    4383         cleanup_and_return:
    4384         xfree((void**)&first_gauss_area_coord);
    4385         xfree((void**)&second_gauss_area_coord);
    4386         xfree((void**)&third_gauss_area_coord);
    4387         xfree((void**)&gauss_weights);
    4388         delete friction;
    4389 
    4390 }
    4391 /*}}}*/
    4392 /*FUNCTION Tria::GradjDragStokes {{{1*/
    4393 void  Tria::GradjDragStokes(Vec gradient){
    4394 
    4395         int i;
    4396 
    4397         /* node data: */
    4398         const int    numgrids=3;
    4399         const int    NDOF2=2;
    4400         double       xyz_list[numgrids][3];
    4401         int          doflist1[numgrids];
    4402         double       dh1dh3[NDOF2][numgrids];
    4403 
    4404         /* grid data: */
    4405         double drag;
    4406         double alpha_complement;
    4407         Friction* friction=NULL;
    4408 
    4409         /* gaussian points: */
    4410         int     num_gauss,ig;
    4411         double* first_gauss_area_coord  =  NULL;
    4412         double* second_gauss_area_coord =  NULL;
    4413         double* third_gauss_area_coord  =  NULL;
    4414         double* gauss_weights           =  NULL;
    4415         double  gauss_weight;
    4416         double  gauss_l1l2l3[3];
    4417         double  gaussgrids[numgrids][numgrids]={{1,0,0},{0,1,0},{0,0,1}};
    4418 
    4419         /* parameters: */
    4420         double  vx,vy,vz;
    4421         double  lambda,mu,xi;
    4422         double  bed,thickness,Neff;
    4423         double  surface_normal[3];
    4424         double  bed_normal[3];
    4425         double  dk[NDOF2];
    4426 
    4427         /*element vector at the gaussian points: */
    4428         double  grade_g[numgrids]={0.0};
    4429         double  grade_g_gaussian[numgrids];
    4430 
    4431         /* Jacobian: */
    4432         double Jdet;
    4433 
    4434         /*nodal functions: */
    4435         double l1l2l3[3];
    4436 
    4437         /* strain rate: */
    4438         double epsilon[3]; /* epsilon=[exx,eyy,exy];*/
    4439 
    4440         /*inputs: */
    4441         bool shelf;
    4442         int  drag_type;
    4443 
    4444         /*parameters: */
    4445         double  cm_noisedmp;
    4446         double  cm_mindmp_slope;
    4447         double  cm_mindmp_value;
    4448         double  cm_maxdmp_value;
    4449         double  cm_maxdmp_slope;
    4450 
    4451         int analysis_type;
    4452 
    4453         /*retrive parameters: */
    4454         parameters->FindParam(&analysis_type,AnalysisTypeEnum);
    4455 
    4456         /*retrieve inputs :*/
    4457         inputs->GetParameterValue(&shelf,ElementOnIceShelfEnum);
    4458         inputs->GetParameterValue(&drag_type,DragTypeEnum);
    4459 
    4460         /*retrieve some parameters: */
    4461         this->parameters->FindParam(&cm_noisedmp,CmNoiseDmpEnum);
    4462         this->parameters->FindParam(&cm_mindmp_value,CmMinDmpValueEnum);
    4463         this->parameters->FindParam(&cm_mindmp_slope,CmMinDmpSlopeEnum);
    4464         this->parameters->FindParam(&cm_maxdmp_value,CmMaxDmpValueEnum);
    4465         this->parameters->FindParam(&cm_maxdmp_slope,CmMaxDmpSlopeEnum);
    4466 
    4467         /*Get out if shelf*/
    4468         if(shelf)return;
    4469 
    4470         /* Get node coordinates and dof list: */
    4471         GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
    4472         GetDofList1(&doflist1[0]);
    4473 
    4474         /*Build frictoin element, needed later: */
    4475         inputs->GetParameterValue(&drag_type,DragTypeEnum);
    4476         friction=new Friction("2d",inputs,matpar,analysis_type);
    4477 
    4478         /* Get gaussian points and weights (make this a statically initialized list of points? fstd): */
    4479         GaussTria( &num_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &gauss_weights, 4);
    4480 
    4481         /* Start  looping on the number of gaussian points: */
    4482         for (ig=0; ig<num_gauss; ig++){
    4483                 /*Pick up the gaussian point: */
    4484                 gauss_weight=*(gauss_weights+ig);
    4485                 gauss_l1l2l3[0]=*(first_gauss_area_coord+ig);
    4486                 gauss_l1l2l3[1]=*(second_gauss_area_coord+ig);
    4487                 gauss_l1l2l3[2]=*(third_gauss_area_coord+ig);
    4488 
    4489                 /*Recover alpha_complement and drag: */
    4490                 if (drag_type==2) friction->GetAlphaComplement(&alpha_complement, gauss_l1l2l3,VxAverageEnum,VyAverageEnum);
    4491                 else alpha_complement=0;
    4492                 inputs->GetParameterValue(&drag, &gauss_l1l2l3[0],DragCoefficientEnum);
    4493 
    4494                 /*recover lambda mu and xi: */
    4495                 inputs->GetParameterValue(&lambda, &gauss_l1l2l3[0],AdjointxEnum);
    4496                 inputs->GetParameterValue(&mu, &gauss_l1l2l3[0],AdjointyEnum);
    4497                 inputs->GetParameterValue(&xi, &gauss_l1l2l3[0],AdjointzEnum);
    4498 
    4499                 /*recover vx vy and vz: */
    4500                 inputs->GetParameterValue(&vx, &gauss_l1l2l3[0],VxEnum);
    4501                 inputs->GetParameterValue(&vy, &gauss_l1l2l3[0],VyEnum);
    4502                 inputs->GetParameterValue(&vz, &gauss_l1l2l3[0],VzEnum);
    4503 
    4504                 /*Get normal vector to the bed */
    4505                 SurfaceNormal(&surface_normal[0],xyz_list);
    4506 
    4507                 bed_normal[0]=-surface_normal[0]; //Program is for surface, so the normal to the bed is the opposite of the result
    4508                 bed_normal[1]=-surface_normal[1];
    4509                 bed_normal[2]=-surface_normal[2];
    4510 
    4511                 /* Get Jacobian determinant: */
    4512                 GetJacobianDeterminant3d(&Jdet, &xyz_list[0][0],gauss_l1l2l3);
    4513 
    4514                 /* Get nodal functions value at gaussian point:*/
    4515                 GetNodalFunctions(l1l2l3, gauss_l1l2l3);
    4516 
    4517                 /*Get nodal functions derivatives*/
    4518                 GetNodalFunctionsDerivatives(&dh1dh3[0][0],&xyz_list[0][0],gauss_l1l2l3);
    4519 
    4520                 /*Get k derivative: dk/dx */
    4521                 inputs->GetParameterDerivativeValue(&dk[0],&xyz_list[0][0],&gauss_l1l2l3[0],DragCoefficientEnum);
    4522 
    4523                 /*Build gradje_g_gaussian vector (actually -dJ/ddrag): */
    4524                 for (i=0;i<numgrids;i++){
    4525                         //standard gradient dJ/dki
    4526                         grade_g_gaussian[i]=(
    4527                                                 -lambda*(2*drag*alpha_complement*(vx - vz*bed_normal[0]*bed_normal[2]))
    4528                                                 -mu    *(2*drag*alpha_complement*(vy - vz*bed_normal[1]*bed_normal[2]))
    4529                                                 -xi    *(2*drag*alpha_complement*(-vx*bed_normal[0]*bed_normal[2]-vy*bed_normal[1]*bed_normal[2]))
    4530                                                 )*Jdet*gauss_weight*l1l2l3[i];
    4531 
    4532                         //Add regularization term
    4533                         grade_g_gaussian[i]+= - cm_noisedmp*Jdet*gauss_weight*(dh1dh3[0][i]*dk[0]+dh1dh3[1][i]*dk[1]);
    4534 
    4535                         //min dampening
    4536                         if(drag<cm_mindmp_value){
    4537                                 grade_g_gaussian[i]+= cm_mindmp_slope*Jdet*gauss_weight*l1l2l3[i];
    4538                         }
    4539 
    4540                         //max dampening
    4541                         if(drag>cm_maxdmp_value){
    4542                                 grade_g_gaussian[i]+= - cm_maxdmp_slope*Jdet*gauss_weight*l1l2l3[i];
    4543                         }
    4544                 }
    4545 
    4546                 /*Add gradje_g_gaussian vector to gradje_g: */
    4547                 for( i=0; i<numgrids; i++)grade_g[i]+=grade_g_gaussian[i];
    4548         }
    4549 
    4550         /*Add grade_g to global vector gradient: */
    4551         VecSetValues(gradient,numgrids,doflist1,(const double*)grade_g,ADD_VALUES);
    4552 
    4553         /*Add grade_g to the inputs of this element: */
    4554         this->inputs->AddInput(new TriaVertexInput(GradientEnum,&grade_g[0]));
    4555 
    4556         cleanup_and_return:
    4557         xfree((void**)&first_gauss_area_coord);
    4558         xfree((void**)&second_gauss_area_coord);
    4559         xfree((void**)&third_gauss_area_coord);
    4560         xfree((void**)&gauss_weights);
    4561         delete friction;
    4562 
    45631023}
    45641024/*}}}*/
     
    47091169}
    47101170/*}}}*/
     1171/*FUNCTION Tria::GradjDrag {{{1*/
     1172void  Tria::GradjDrag(Vec gradient){
     1173
     1174
     1175        int i;
     1176
     1177        /* node data: */
     1178        const int    numgrids=3;
     1179        const int    NDOF2=2;
     1180        const int    numdof=NDOF2*numgrids;
     1181        double       xyz_list[numgrids][3];
     1182        int          doflist1[numgrids];
     1183        double       dh1dh3[NDOF2][numgrids];
     1184
     1185        /* grid data: */
     1186        double adjx_list[numgrids];
     1187        double adjy_list[numgrids];
     1188
     1189        /* gaussian points: */
     1190        int     num_gauss,ig;
     1191        double* first_gauss_area_coord  =  NULL;
     1192        double* second_gauss_area_coord =  NULL;
     1193        double* third_gauss_area_coord  =  NULL;
     1194        double* gauss_weights           =  NULL;
     1195        double  gauss_weight;
     1196        double  gauss_l1l2l3[3];
     1197
     1198        /* parameters: */
     1199        double  dk[NDOF2];
     1200        double  vx,vy;
     1201        double  lambda,mu;
     1202        double  bed,thickness,Neff;
     1203        double  alpha_complement;
     1204        int     drag_type;
     1205        double  drag;
     1206        Friction* friction=NULL;
     1207
     1208        /*element vector at the gaussian points: */
     1209        double  grade_g[numgrids]={0.0};
     1210        double  grade_g_gaussian[numgrids];
     1211
     1212        /* Jacobian: */
     1213        double Jdet;
     1214
     1215        /*nodal functions: */
     1216        double l1l2l3[3];
     1217
     1218        /* strain rate: */
     1219        double epsilon[3]; /* epsilon=[exx,eyy,exy];*/
     1220
     1221        /*inputs: */
     1222        bool shelf;
     1223
     1224        /*parameters: */
     1225        double  cm_noisedmp;
     1226        double  cm_mindmp_slope;
     1227        double  cm_mindmp_value;
     1228        double  cm_maxdmp_value;
     1229        double  cm_maxdmp_slope;
     1230
     1231        int analysis_type;
     1232
     1233        /*retrive parameters: */
     1234        parameters->FindParam(&analysis_type,AnalysisTypeEnum);
     1235
     1236        /*retrieve inputs :*/
     1237        inputs->GetParameterValue(&shelf,ElementOnIceShelfEnum);
     1238
     1239        /*retrieve some parameters: */
     1240        this->parameters->FindParam(&cm_noisedmp,CmNoiseDmpEnum);
     1241        this->parameters->FindParam(&cm_mindmp_value,CmMinDmpValueEnum);
     1242        this->parameters->FindParam(&cm_mindmp_slope,CmMinDmpSlopeEnum);
     1243        this->parameters->FindParam(&cm_maxdmp_value,CmMaxDmpValueEnum);
     1244        this->parameters->FindParam(&cm_maxdmp_slope,CmMaxDmpSlopeEnum);
     1245
     1246
     1247        /*Get out if shelf*/
     1248        if(shelf)return;
     1249
     1250        /* Get node coordinates and dof list: */
     1251        GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
     1252        GetDofList1(&doflist1[0]);
     1253
     1254        /*Build frictoin element, needed later: */
     1255        inputs->GetParameterValue(&drag_type,DragTypeEnum);
     1256        friction=new Friction("2d",inputs,matpar,analysis_type);
     1257
     1258        /* Get gaussian points and weights (make this a statically initialized list of points? fstd): */
     1259        GaussTria( &num_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &gauss_weights, 4);
     1260
     1261        /* Start  looping on the number of gaussian points: */
     1262        for (ig=0; ig<num_gauss; ig++){
     1263                /*Pick up the gaussian point: */
     1264                gauss_weight=*(gauss_weights+ig);
     1265                gauss_l1l2l3[0]=*(first_gauss_area_coord+ig);
     1266                gauss_l1l2l3[1]=*(second_gauss_area_coord+ig);
     1267                gauss_l1l2l3[2]=*(third_gauss_area_coord+ig);
     1268
     1269                /*Build alpha_complement_list: */
     1270                if (drag_type==2) friction->GetAlphaComplement(&alpha_complement, gauss_l1l2l3,VxAverageEnum,VyAverageEnum);
     1271                else alpha_complement=0;
     1272       
     1273                /*Recover alpha_complement and k: */
     1274                inputs->GetParameterValue(&drag, gauss_l1l2l3,DragCoefficientEnum);
     1275
     1276                /*recover lambda and mu: */
     1277                inputs->GetParameterValue(&lambda, gauss_l1l2l3,AdjointxEnum);
     1278                inputs->GetParameterValue(&mu, gauss_l1l2l3,AdjointyEnum);
     1279                       
     1280                /*recover vx and vy: */
     1281                inputs->GetParameterValue(&vx, gauss_l1l2l3,VxEnum);
     1282                inputs->GetParameterValue(&vy, gauss_l1l2l3,VyEnum);
     1283
     1284                /* Get Jacobian determinant: */
     1285                GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0],gauss_l1l2l3);
     1286               
     1287                /* Get nodal functions value at gaussian point:*/
     1288                GetNodalFunctions(l1l2l3, gauss_l1l2l3);
     1289
     1290                /*Get nodal functions derivatives*/
     1291                GetNodalFunctionsDerivatives(&dh1dh3[0][0],&xyz_list[0][0],gauss_l1l2l3);
     1292
     1293                /*Get k derivative: dk/dx */
     1294                inputs->GetParameterDerivativeValue(&dk[0],&xyz_list[0][0],&gauss_l1l2l3[0],DragCoefficientEnum);
     1295
     1296                /*Build gradje_g_gaussian vector (actually -dJ/ddrag): */
     1297                for (i=0;i<numgrids;i++){
     1298
     1299                        //standard term dJ/dki
     1300                        grade_g_gaussian[i]=-2*drag*alpha_complement*((lambda*vx+mu*vy))*Jdet*gauss_weight*l1l2l3[i];
     1301
     1302                        //noise dampening d/dki(1/2*(dk/dx)^2)
     1303                        grade_g_gaussian[i]+=-cm_noisedmp*Jdet*gauss_weight*(dh1dh3[0][i]*dk[0]+dh1dh3[1][i]*dk[1]);
     1304                       
     1305                        //min dampening
     1306                        if(drag<cm_mindmp_value){
     1307                                grade_g_gaussian[i]+=cm_mindmp_slope*Jdet*gauss_weight*l1l2l3[i];
     1308                        }
     1309
     1310                        //max dampening
     1311                        if(drag>cm_maxdmp_value){
     1312                                grade_g_gaussian[i]+= - cm_maxdmp_slope*Jdet*gauss_weight*l1l2l3[i];
     1313                        }
     1314                }
     1315               
     1316                /*Add gradje_g_gaussian vector to gradje_g: */
     1317                for( i=0; i<numgrids; i++)grade_g[i]+=grade_g_gaussian[i];
     1318        }
     1319
     1320
     1321        /*Add grade_g to global vector gradient: */
     1322        VecSetValues(gradient,numgrids,doflist1,(const double*)grade_g,ADD_VALUES);
     1323
     1324        cleanup_and_return:
     1325        xfree((void**)&first_gauss_area_coord);
     1326        xfree((void**)&second_gauss_area_coord);
     1327        xfree((void**)&third_gauss_area_coord);
     1328        xfree((void**)&gauss_weights);
     1329        delete friction;
     1330
     1331}
     1332/*}}}*/
     1333/*FUNCTION Tria::InputAXPY(int YEnum, double scalar, int XEnum);{{{1*/
     1334void  Tria::InputAXPY(int YEnum, double scalar, int XEnum){
     1335
     1336        Input* xinput=NULL;
     1337        Input* yinput=NULL;
     1338
     1339        /*Find x and y inputs: */
     1340        xinput=(Input*)this->inputs->GetInput(XEnum);
     1341        yinput=(Input*)this->inputs->GetInput(YEnum);
     1342
     1343        /*some checks: */
     1344        if(!xinput || !yinput) ISSMERROR("%s%s%s%s%s"," input ",EnumAsString(XEnum)," or input ",EnumAsString(YEnum)," could not be found!");
     1345
     1346        /*Scale: */
     1347        yinput->AXPY(xinput,scalar);
     1348}
     1349/*}}}*/
     1350/*FUNCTION Tria::InputControlConstrain(int control_type, double cm_min, double cm_max){{{1*/
     1351void  Tria::InputControlConstrain(int control_type, double cm_min, double cm_max){
     1352
     1353        Input* input=NULL;
     1354
     1355        /*Find input: */
     1356        input=(Input*)this->inputs->GetInput(control_type);
     1357       
     1358        /*Do nothing if we  don't find it: */
     1359        if(!input)return;
     1360
     1361        /*Constrain input using cm_min and cm_max: */
     1362        input->Constrain(cm_min,cm_max);
     1363
     1364}
     1365/*}}}*/
     1366/*FUNCTION Tria::InputConvergence(int* pconverged, double* eps, int* enums,int num_enums,int* criterionenums,double* criterionvalues,int num_criterionenums){{{1*/
     1367void  Tria::InputConvergence(int* pconverged,double* eps, int* enums,int num_enums,int* criterionenums,double* criterionvalues,int num_criterionenums){
     1368
     1369        int i;
     1370        Input** new_inputs=NULL;
     1371        Input** old_inputs=NULL;
     1372        int     converged=1;
     1373
     1374        new_inputs=(Input**)xmalloc(num_enums/2*sizeof(Input*)); //half the enums are for the new inputs
     1375        old_inputs=(Input**)xmalloc(num_enums/2*sizeof(Input*)); //half the enums are for the old inputs
     1376       
     1377        for(i=0;i<num_enums/2;i++){
     1378                new_inputs[i]=(Input*)this->inputs->GetInput(enums[2*i+0]);
     1379                old_inputs[i]=(Input*)this->inputs->GetInput(enums[2*i+1]);
     1380                if(!new_inputs[i])ISSMERROR("%s%s"," could not find input with enum ",EnumAsString(enums[2*i+0]));
     1381                if(!old_inputs[i])ISSMERROR("%s%s"," could not find input with enum ",EnumAsString(enums[2*i+0]));
     1382        }
     1383
     1384        /*ok, we've got the inputs (new and old), now loop throught the number of criterions and fill the eps array:*/
     1385        for(i=0;i<num_criterionenums;i++){
     1386                IsInputConverged(eps+i,new_inputs,old_inputs,num_enums/2,criterionenums[i]);
     1387                if(eps[i]>criterionvalues[i]) converged=0;
     1388        }
     1389
     1390        /*Assign output pointers:*/
     1391        *pconverged=converged;
     1392
     1393}
     1394/*}}}*/
     1395/*FUNCTION Tria::InputDepthAverageAtBase {{{1*/
     1396void  Tria::InputDepthAverageAtBase(int enum_type,int average_enum_type){
     1397
     1398        /*New input*/
     1399        Input* oldinput=NULL;
     1400        Input* newinput=NULL;
     1401
     1402        /*copy input of enum_type*/
     1403        oldinput=this->inputs->GetInput(enum_type);
     1404        if(!oldinput)ISSMERROR("%s%s"," could not find old input with enum: ",EnumAsString(enum_type));
     1405        newinput=(Input*)oldinput->copy();
     1406
     1407        /*Assign new name (average)*/
     1408        newinput->ChangeEnum(average_enum_type);
     1409
     1410        /*Add new input to current element*/
     1411        this->inputs->AddInput(newinput);
     1412
     1413}
     1414/*}}}*/
     1415/*FUNCTION Tria::InputDuplicate(int original_enum,int new_enum){{{1*/
     1416void  Tria::InputDuplicate(int original_enum,int new_enum){
     1417
     1418        Input* original=NULL;
     1419        Input* copy=NULL;
     1420
     1421        /*Make a copy of the original input: */
     1422        original=(Input*)this->inputs->GetInput(original_enum);
     1423        copy=(Input*)original->copy();
     1424
     1425        /*Change copy enum to reinitialized_enum: */
     1426        copy->ChangeEnum(new_enum);
     1427
     1428        /*Add copy into inputs, it will wipe off the one already there: */
     1429        inputs->AddObject((Input*)copy);
     1430}
     1431/*}}}*/
     1432/*FUNCTION Tria::InputScale(int enum_type,double scale_factor){{{1*/
     1433void  Tria::InputScale(int enum_type,double scale_factor){
     1434
     1435        Input* input=NULL;
     1436
     1437        /*Make a copy of the original input: */
     1438        input=(Input*)this->inputs->GetInput(enum_type);
     1439
     1440        /*Scale: */
     1441        input->Scale(scale_factor);
     1442}
     1443/*}}}*/
     1444/*FUNCTION Tria::InputToResult(int enum_type,int step,double time){{{1*/
     1445void  Tria::InputToResult(int enum_type,int step,double time){
     1446
     1447        int    i;
     1448        bool   found = false;
     1449        Input *input = NULL;
     1450
     1451        /*Go through all the input objects, and find the one corresponding to enum_type, if it exists: */
     1452        for (i=0;i<this->inputs->Size();i++){
     1453                input=(Input*)this->inputs->GetObjectByOffset(i);
     1454                if (input->EnumType()==enum_type){
     1455                        found=true;
     1456                        break;
     1457                }
     1458        }
     1459
     1460        /*If we don't find it, no big deal, just don't do the transfer. Otherwise, build a new Result
     1461         * object out of the input, with the additional step and time information: */
     1462        this->results->AddObject((Object*)input->SpawnResult(step,time));
     1463
     1464}
     1465/*}}}*/
    47111466/*FUNCTION Tria::MassFlux {{{1*/
    47121467double Tria::MassFlux( double* segment){
     
    47661521                                );
    47671522        return mass_flux;
     1523}
     1524/*}}}*/
     1525/*FUNCTION Tria::MaxAbsVx(double* pmaxabsvx, bool process_units);{{{1*/
     1526void  Tria::MaxAbsVx(double* pmaxabsvx, bool process_units){
     1527
     1528        int i;
     1529        int dim;
     1530        const int numgrids=3;
     1531        double  gaussgrids[numgrids][numgrids]={{1,0,0},{0,1,0},{0,0,1}};
     1532        double  vx_values[numgrids];
     1533        double  maxabsvx;
     1534
     1535        /*retrieve dim parameter: */
     1536        parameters->FindParam(&dim,DimEnum);
     1537
     1538        /*retrive velocity values at nodes */
     1539        inputs->GetParameterValues(&vx_values[0],&gaussgrids[0][0],numgrids,VxEnum);
     1540
     1541        /*now, compute maximum:*/
     1542        maxabsvx=fabs(vx_values[0]);
     1543        for(i=1;i<numgrids;i++){
     1544                if (fabs(vx_values[i])>maxabsvx)maxabsvx=fabs(vx_values[i]);
     1545        }
     1546
     1547        /*Assign output pointers:*/
     1548        *pmaxabsvx=maxabsvx;
     1549}
     1550/*}}}*/
     1551/*FUNCTION Tria::MaxAbsVy(double* pmaxabsvy, bool process_units);{{{1*/
     1552void  Tria::MaxAbsVy(double* pmaxabsvy, bool process_units){
     1553
     1554        int i;
     1555        int dim;
     1556        const int numgrids=3;
     1557        double  gaussgrids[numgrids][numgrids]={{1,0,0},{0,1,0},{0,0,1}};
     1558        double  vy_values[numgrids];
     1559        double  maxabsvy;
     1560
     1561        /*retrieve dim parameter: */
     1562        parameters->FindParam(&dim,DimEnum);
     1563
     1564        /*retrive velocity values at nodes */
     1565        inputs->GetParameterValues(&vy_values[0],&gaussgrids[0][0],numgrids,VyEnum);
     1566
     1567        /*now, compute maximum:*/
     1568        maxabsvy=fabs(vy_values[0]);
     1569        for(i=1;i<numgrids;i++){
     1570                if (fabs(vy_values[i])>maxabsvy)maxabsvy=fabs(vy_values[i]);
     1571        }
     1572
     1573        /*Assign output pointers:*/
     1574        *pmaxabsvy=maxabsvy;
     1575}
     1576/*}}}*/
     1577/*FUNCTION Tria::MaxAbsVz(double* pmaxabsvz, bool process_units);{{{1*/
     1578void  Tria::MaxAbsVz(double* pmaxabsvz, bool process_units){
     1579
     1580        int i;
     1581        int dim;
     1582        const int numgrids=3;
     1583        double  gaussgrids[numgrids][numgrids]={{1,0,0},{0,1,0},{0,0,1}};
     1584        double  vz_values[numgrids];
     1585        double  maxabsvz;
     1586
     1587        /*retrieve dim parameter: */
     1588        parameters->FindParam(&dim,DimEnum);
     1589
     1590        /*retrive velocity values at nodes */
     1591        inputs->GetParameterValues(&vz_values[0],&gaussgrids[0][0],numgrids,VzEnum);
     1592
     1593        /*now, compute maximum:*/
     1594        maxabsvz=fabs(vz_values[0]);
     1595        for(i=1;i<numgrids;i++){
     1596                if (fabs(vz_values[i])>maxabsvz)maxabsvz=fabs(vz_values[i]);
     1597        }
     1598
     1599        /*Assign output pointers:*/
     1600        *pmaxabsvz=maxabsvz;
     1601}
     1602/*}}}*/
     1603/*FUNCTION Tria::MaxVel(double* pmaxvel, bool process_units);{{{1*/
     1604void  Tria::MaxVel(double* pmaxvel, bool process_units){
     1605
     1606        int i;
     1607        int dim;
     1608        const int numgrids=3;
     1609        double  gaussgrids[numgrids][3]={{1,0,0},{0,1,0},{0,0,1}};
     1610        double  vx_values[numgrids];
     1611        double  vy_values[numgrids];
     1612        double  vz_values[numgrids];
     1613        double  vel_values[numgrids];
     1614        double  maxvel;
     1615
     1616        /*retrieve dim parameter: */
     1617        parameters->FindParam(&dim,DimEnum);
     1618
     1619        /*retrive velocity values at nodes */
     1620        inputs->GetParameterValues(&vx_values[0],&gaussgrids[0][0],numgrids,VxEnum);
     1621        inputs->GetParameterValues(&vy_values[0],&gaussgrids[0][0],numgrids,VyEnum);
     1622        if(dim==3) inputs->GetParameterValues(&vz_values[0],&gaussgrids[0][0],numgrids,VzEnum);
     1623
     1624        /*now, compute maximum of velocity :*/
     1625        if(dim==2){
     1626                for(i=0;i<numgrids;i++)vel_values[i]=sqrt(pow(vx_values[i],2)+pow(vy_values[i],2));
     1627        }
     1628        else{
     1629                for(i=0;i<numgrids;i++)vel_values[i]=sqrt(pow(vx_values[i],2)+pow(vy_values[i],2)+pow(vz_values[i],2));
     1630        }
     1631
     1632        /*now, compute maximum:*/
     1633        maxvel=vel_values[0];
     1634        for(i=1;i<numgrids;i++){
     1635                if (vel_values[i]>maxvel)maxvel=vel_values[i];
     1636        }
     1637
     1638        /*Assign output pointers:*/
     1639        *pmaxvel=maxvel;
     1640
     1641}
     1642/*}}}*/
     1643/*FUNCTION Tria::MaxVx(double* pmaxvx, bool process_units);{{{1*/
     1644void  Tria::MaxVx(double* pmaxvx, bool process_units){
     1645
     1646        int i;
     1647        int dim;
     1648        const int numgrids=3;
     1649        double  gaussgrids[numgrids][numgrids]={{1,0,0},{0,1,0},{0,0,1}};
     1650        double  vx_values[numgrids];
     1651        double  maxvx;
     1652
     1653        /*retrieve dim parameter: */
     1654        parameters->FindParam(&dim,DimEnum);
     1655
     1656        /*retrive velocity values at nodes */
     1657        inputs->GetParameterValues(&vx_values[0],&gaussgrids[0][0],numgrids,VxEnum);
     1658
     1659        /*now, compute maximum:*/
     1660        maxvx=vx_values[0];
     1661        for(i=1;i<numgrids;i++){
     1662                if (vx_values[i]>maxvx)maxvx=vx_values[i];
     1663        }
     1664
     1665        /*Assign output pointers:*/
     1666        *pmaxvx=maxvx;
     1667
     1668}
     1669/*}}}*/
     1670/*FUNCTION Tria::MaxVy(double* pmaxvy, bool process_units);{{{1*/
     1671void  Tria::MaxVy(double* pmaxvy, bool process_units){
     1672
     1673        int i;
     1674        int dim;
     1675        const int numgrids=3;
     1676        double  gaussgrids[numgrids][numgrids]={{1,0,0},{0,1,0},{0,0,1}};
     1677        double  vy_values[numgrids];
     1678        double  maxvy;
     1679
     1680        /*retrieve dim parameter: */
     1681        parameters->FindParam(&dim,DimEnum);
     1682
     1683        /*retrive velocity values at nodes */
     1684        inputs->GetParameterValues(&vy_values[0],&gaussgrids[0][0],numgrids,VyEnum);
     1685
     1686        /*now, compute maximum:*/
     1687        maxvy=vy_values[0];
     1688        for(i=1;i<numgrids;i++){
     1689                if (vy_values[i]>maxvy)maxvy=vy_values[i];
     1690        }
     1691
     1692        /*Assign output pointers:*/
     1693        *pmaxvy=maxvy;
     1694
     1695}
     1696/*}}}*/
     1697/*FUNCTION Tria::MaxVz(double* pmaxvz, bool process_units);{{{1*/
     1698void  Tria::MaxVz(double* pmaxvz, bool process_units){
     1699
     1700        int i;
     1701        int dim;
     1702        const int numgrids=3;
     1703        double  gaussgrids[numgrids][numgrids]={{1,0,0},{0,1,0},{0,0,1}};
     1704        double  vz_values[numgrids];
     1705        double  maxvz;
     1706
     1707        /*retrieve dim parameter: */
     1708        parameters->FindParam(&dim,DimEnum);
     1709
     1710        /*retrive velocity values at nodes */
     1711        inputs->GetParameterValues(&vz_values[0],&gaussgrids[0][0],numgrids,VzEnum);
     1712
     1713        /*now, compute maximum:*/
     1714        maxvz=vz_values[0];
     1715        for(i=1;i<numgrids;i++){
     1716                if (vz_values[i]>maxvz)maxvz=vz_values[i];
     1717        }
     1718
     1719        /*Assign output pointers:*/
     1720        *pmaxvz=maxvz;
     1721
     1722}
     1723/*}}}*/
     1724/*FUNCTION Tria::MinVel(double* pminvel, bool process_units);{{{1*/
     1725void  Tria::MinVel(double* pminvel, bool process_units){
     1726
     1727        int i;
     1728        int dim;
     1729        const int numgrids=3;
     1730        double  gaussgrids[numgrids][3]={{1,0,0},{0,1,0},{0,0,1}};
     1731        double  vx_values[numgrids];
     1732        double  vy_values[numgrids];
     1733        double  vz_values[numgrids];
     1734        double  vel_values[numgrids];
     1735        double  minvel;
     1736
     1737        /*retrieve dim parameter: */
     1738        parameters->FindParam(&dim,DimEnum);
     1739
     1740        /*retrive velocity values at nodes */
     1741        inputs->GetParameterValues(&vx_values[0],&gaussgrids[0][0],numgrids,VxEnum);
     1742        inputs->GetParameterValues(&vy_values[0],&gaussgrids[0][0],numgrids,VyEnum);
     1743        if(dim==3) inputs->GetParameterValues(&vz_values[0],&gaussgrids[0][0],numgrids,VzEnum);
     1744
     1745        /*now, compute minimum of velocity :*/
     1746        if(dim==2){
     1747                for(i=0;i<numgrids;i++)vel_values[i]=sqrt(pow(vx_values[i],2)+pow(vy_values[i],2));
     1748        }
     1749        else{
     1750                for(i=0;i<numgrids;i++)vel_values[i]=sqrt(pow(vx_values[i],2)+pow(vy_values[i],2)+pow(vz_values[i],2));
     1751        }
     1752
     1753        /*now, compute minimum:*/
     1754        minvel=vel_values[0];
     1755        for(i=1;i<numgrids;i++){
     1756                if (vel_values[i]<minvel)minvel=vel_values[i];
     1757        }
     1758
     1759        /*Assign output pointers:*/
     1760        *pminvel=minvel;
     1761
     1762}
     1763/*}}}*/
     1764/*FUNCTION Tria::MinVx(double* pminvx, bool process_units);{{{1*/
     1765void  Tria::MinVx(double* pminvx, bool process_units){
     1766
     1767        int i;
     1768        int dim;
     1769        const int numgrids=3;
     1770        double  gaussgrids[numgrids][numgrids]={{1,0,0},{0,1,0},{0,0,1}};
     1771        double  vx_values[numgrids];
     1772        double  minvx;
     1773
     1774        /*retrieve dim parameter: */
     1775        parameters->FindParam(&dim,DimEnum);
     1776
     1777        /*retrive velocity values at nodes */
     1778        inputs->GetParameterValues(&vx_values[0],&gaussgrids[0][0],numgrids,VxEnum);
     1779
     1780        /*now, compute minimum:*/
     1781        minvx=vx_values[0];
     1782        for(i=1;i<numgrids;i++){
     1783                if (vx_values[i]<minvx)minvx=vx_values[i];
     1784        }
     1785
     1786        /*Assign output pointers:*/
     1787        *pminvx=minvx;
     1788
     1789}
     1790/*}}}*/
     1791/*FUNCTION Tria::MinVy(double* pminvy, bool process_units);{{{1*/
     1792void  Tria::MinVy(double* pminvy, bool process_units){
     1793
     1794        int i;
     1795        int dim;
     1796        const int numgrids=3;
     1797        double  gaussgrids[numgrids][numgrids]={{1,0,0},{0,1,0},{0,0,1}};
     1798        double  vy_values[numgrids];
     1799        double  minvy;
     1800
     1801        /*retrieve dim parameter: */
     1802        parameters->FindParam(&dim,DimEnum);
     1803
     1804        /*retrive velocity values at nodes */
     1805        inputs->GetParameterValues(&vy_values[0],&gaussgrids[0][0],numgrids,VyEnum);
     1806
     1807        /*now, compute minimum:*/
     1808        minvy=vy_values[0];
     1809        for(i=1;i<numgrids;i++){
     1810                if (vy_values[i]<minvy)minvy=vy_values[i];
     1811        }
     1812
     1813        /*Assign output pointers:*/
     1814        *pminvy=minvy;
     1815
     1816}
     1817/*}}}*/
     1818/*FUNCTION Tria::MinVz(double* pminvz, bool process_units);{{{1*/
     1819void  Tria::MinVz(double* pminvz, bool process_units){
     1820
     1821        int i;
     1822        int dim;
     1823        const int numgrids=3;
     1824        double  gaussgrids[numgrids][numgrids]={{1,0,0},{0,1,0},{0,0,1}};
     1825        double  vz_values[numgrids];
     1826        double  minvz;
     1827
     1828        /*retrieve dim parameter: */
     1829        parameters->FindParam(&dim,DimEnum);
     1830
     1831        /*retrive velocity values at nodes */
     1832        inputs->GetParameterValues(&vz_values[0],&gaussgrids[0][0],numgrids,VzEnum);
     1833
     1834        /*now, compute minimum:*/
     1835        minvz=vz_values[0];
     1836        for(i=1;i<numgrids;i++){
     1837                if (vz_values[i]<minvz)minvz=vz_values[i];
     1838        }
     1839
     1840        /*Assign output pointers:*/
     1841        *pminvz=minvz;
     1842
    47681843}
    47691844/*}}}*/
     
    49602035}
    49612036/*}}}*/
    4962 /*FUNCTION Tria::SetClone {{{1*/
    4963 void  Tria::SetClone(int* minranks){
    4964 
    4965         ISSMERROR("not implemented yet");
    4966 }
    4967 /*}}}1*/
    4968 /*FUNCTION Tria::SurfaceNormal{{{1*/
    4969 
    4970 void Tria::SurfaceNormal(double* surface_normal, double xyz_list[3][3]){
     2037/*FUNCTION Tria::PatchFill(int* prow, Patch* patch){{{1*/
     2038void  Tria::PatchFill(int* prow, Patch* patch){
    49712039
    49722040        int i;
    4973         double v13[3];
    4974         double v23[3];
    4975         double normal[3];
    4976         double normal_norm;
    4977 
    4978         for (i=0;i<3;i++){
    4979                 v13[i]=xyz_list[0][i]-xyz_list[2][i];
    4980                 v23[i]=xyz_list[1][i]-xyz_list[2][i];
    4981         }
    4982 
    4983         normal[0]=v13[1]*v23[2]-v13[2]*v23[1];
    4984         normal[1]=v13[2]*v23[0]-v13[0]*v23[2];
    4985         normal[2]=v13[0]*v23[1]-v13[1]*v23[0];
    4986 
    4987         normal_norm=sqrt( pow(normal[0],(double)2)+pow(normal[1],(double)2)+pow(normal[2],(double)2) );
    4988 
    4989         *(surface_normal)=normal[0]/normal_norm;
    4990         *(surface_normal+1)=normal[1]/normal_norm;
    4991         *(surface_normal+2)=normal[2]/normal_norm;
    4992 
    4993 }
    4994 /*}}}*/
    4995 /*FUNCTION Tria::SurfaceArea {{{1*/
    4996 double Tria::SurfaceArea(void){
    4997 
    4998         int i;
    4999 
    5000         /* output: */
    5001         double S;
    5002 
    5003         /* node data: */
    5004         int numgrids=3;
    5005         double xyz_list[numgrids][3];
    5006         double v13[3];
    5007         double v23[3];
    5008         double normal[3];
    5009 
    5010         /*inputs: */
    5011         bool onwater;
    5012         int  fit;
    5013 
    5014         /*retrieve inputs :*/
    5015         inputs->GetParameterValue(&fit,FitEnum);
    5016         inputs->GetParameterValue(&onwater,ElementOnWaterEnum);
    5017 
    5018         /*If fit!=3, do not compute surface: */
    5019         if(fit!=3)return 0;
    5020 
    5021         /*If on water, return 0: */
    5022         if(onwater)return 0;
    5023 
    5024         /* Get node coordinates and dof list: */
    5025         GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
    5026 
    5027         for (i=0;i<3;i++){
    5028                 v13[i]=xyz_list[0][i]-xyz_list[2][i];
    5029                 v23[i]=xyz_list[1][i]-xyz_list[2][i];
    5030         }
    5031 
    5032         normal[0]=v13[1]*v23[2]-v13[2]*v23[1];
    5033         normal[1]=v13[2]*v23[0]-v13[0]*v23[2];
    5034         normal[2]=v13[0]*v23[1]-v13[1]*v23[0];
    5035 
    5036         S = 0.5 * sqrt(pow(normal[0],(double)2)+pow(normal[1],(double)2)+pow(normal[2],(double)2));
    5037 
    5038         /*Return: */
    5039         return S;
    5040 }
    5041 /*}}}*/
    5042 /*FUNCTION Tria::InputUpdateFromVector(double* vector, int name, int type);{{{1*/
    5043 void  Tria::InputUpdateFromVector(double* vector, int name, int type){
    5044 
    5045         /*Check that name is an element input*/
    5046         if (!IsInput(name)) return;
    5047 
    5048         switch(type){
    5049 
    5050                 case VertexEnum:
    5051 
    5052                         /*New PentaVertexInpu*/
    5053                         double values[3];
    5054 
    5055                         /*Get values on the 6 vertices*/
    5056                         for (int i=0;i<3;i++){
    5057                                 values[i]=vector[this->nodes[i]->GetVertexDof()];
    5058                         }
    5059 
    5060                         /*update input*/
    5061                         this->inputs->AddInput(new TriaVertexInput(name,values));
    5062                         return;
    5063 
    5064                 default:
    5065 
    5066                         ISSMERROR("type %i (%s) not implemented yet",type,EnumAsString(type));
    5067         }
    5068 }
    5069 /*}}}*/
    5070 /*FUNCTION Tria::InputUpdateFromVector(int* vector, int name, int type);{{{1*/
    5071 void  Tria::InputUpdateFromVector(int* vector, int name, int type){
    5072         ISSMERROR(" not supported yet!");
    5073 }
    5074 /*}}}*/
    5075 /*FUNCTION Tria::InputUpdateFromVector(bool* vector, int name, int type);{{{1*/
    5076 void  Tria::InputUpdateFromVector(bool* vector, int name, int type){
    5077         ISSMERROR(" not supported yet!");
    5078 }
    5079 /*}}}*/
    5080 /*FUNCTION Tria::InputUpdateFromConstant(int value, int name);{{{1*/
    5081 void  Tria::InputUpdateFromConstant(int constant, int name){
    5082         /*Nothing updated for now*/
    5083 }
    5084 /*}}}*/
    5085 /*FUNCTION Tria::InputUpdateFromConstant(double value, int name);{{{1*/
    5086 void  Tria::InputUpdateFromConstant(double constant, int name){
    5087         /*Nothing updated for now*/
    5088 }
    5089 /*}}}*/
    5090 /*FUNCTION Tria::InputUpdateFromConstant(bool value, int name);{{{1*/
    5091 void  Tria::InputUpdateFromConstant(bool constant, int name){
    5092         /*Nothing updated for now*/
    5093 }
    5094 /*}}}*/
    5095 /*FUNCTION Tria::InputDepthAverageAtBase {{{1*/
    5096 void  Tria::InputDepthAverageAtBase(int enum_type,int average_enum_type){
    5097 
    5098         /*New input*/
    5099         Input* oldinput=NULL;
    5100         Input* newinput=NULL;
    5101 
    5102         /*copy input of enum_type*/
    5103         oldinput=this->inputs->GetInput(enum_type);
    5104         if(!oldinput)ISSMERROR("%s%s"," could not find old input with enum: ",EnumAsString(enum_type));
    5105         newinput=(Input*)oldinput->copy();
    5106 
    5107         /*Assign new name (average)*/
    5108         newinput->ChangeEnum(average_enum_type);
    5109 
    5110         /*Add new input to current element*/
    5111         this->inputs->AddInput(newinput);
    5112 
     2041        int row;
     2042        int vertices_ids[3];
     2043
     2044
     2045        /*recover pointer: */
     2046        row=*prow;
     2047               
     2048        /*will be needed later: */
     2049        for(i=0;i<3;i++) vertices_ids[i]=nodes[i]->GetVertexId(); //vertices id start at column 3 of the patch.
     2050
     2051        for(i=0;i<this->results->Size();i++){
     2052                ElementResult* elementresult=(ElementResult*)this->results->GetObjectByOffset(i);
     2053
     2054                /*For this result,fill the information in the Patch object (element id + vertices ids), and then hand
     2055                 *it to the result object, to fill the rest: */
     2056                patch->fillelementinfo(row,this->id,vertices_ids,3);
     2057                elementresult->PatchFill(row,patch);
     2058
     2059                /*increment rower: */
     2060                row++;
     2061        }
     2062
     2063        /*Assign output pointers:*/
     2064        *prow=row;
    51132065}
    51142066/*}}}*/
     
    51402092}
    51412093/*}}}*/
    5142 /*FUNCTION Tria::PatchFill(int* prow, Patch* patch){{{1*/
    5143 void  Tria::PatchFill(int* prow, Patch* patch){
     2094/*FUNCTION Tria::ProcessResultsUnits(void){{{1*/
     2095void  Tria::ProcessResultsUnits(void){
    51442096
    51452097        int i;
    5146         int row;
    5147         int vertices_ids[3];
    5148 
    5149 
    5150         /*recover pointer: */
    5151         row=*prow;
    5152                
    5153         /*will be needed later: */
    5154         for(i=0;i<3;i++) vertices_ids[i]=nodes[i]->GetVertexId(); //vertices id start at column 3 of the patch.
    51552098
    51562099        for(i=0;i<this->results->Size();i++){
    51572100                ElementResult* elementresult=(ElementResult*)this->results->GetObjectByOffset(i);
    5158 
    5159                 /*For this result,fill the information in the Patch object (element id + vertices ids), and then hand
    5160                  *it to the result object, to fill the rest: */
    5161                 patch->fillelementinfo(row,this->id,vertices_ids,3);
    5162                 elementresult->PatchFill(row,patch);
    5163 
    5164                 /*increment rower: */
    5165                 row++;
     2101                elementresult->ProcessUnits(this->parameters);
     2102        }
     2103
     2104}
     2105/*}}}*/
     2106/*FUNCTION Tria::SurfaceArea {{{1*/
     2107double Tria::SurfaceArea(void){
     2108
     2109        int i;
     2110
     2111        /* output: */
     2112        double S;
     2113
     2114        /* node data: */
     2115        int numgrids=3;
     2116        double xyz_list[numgrids][3];
     2117        double v13[3];
     2118        double v23[3];
     2119        double normal[3];
     2120
     2121        /*inputs: */
     2122        bool onwater;
     2123        int  fit;
     2124
     2125        /*retrieve inputs :*/
     2126        inputs->GetParameterValue(&fit,FitEnum);
     2127        inputs->GetParameterValue(&onwater,ElementOnWaterEnum);
     2128
     2129        /*If fit!=3, do not compute surface: */
     2130        if(fit!=3)return 0;
     2131
     2132        /*If on water, return 0: */
     2133        if(onwater)return 0;
     2134
     2135        /* Get node coordinates and dof list: */
     2136        GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
     2137
     2138        for (i=0;i<3;i++){
     2139                v13[i]=xyz_list[0][i]-xyz_list[2][i];
     2140                v23[i]=xyz_list[1][i]-xyz_list[2][i];
     2141        }
     2142
     2143        normal[0]=v13[1]*v23[2]-v13[2]*v23[1];
     2144        normal[1]=v13[2]*v23[0]-v13[0]*v23[2];
     2145        normal[2]=v13[0]*v23[1]-v13[1]*v23[0];
     2146
     2147        S = 0.5 * sqrt(pow(normal[0],(double)2)+pow(normal[1],(double)2)+pow(normal[2],(double)2));
     2148
     2149        /*Return: */
     2150        return S;
     2151}
     2152/*}}}*/
     2153/*FUNCTION Tria::Update(IoModel* iomodel,int analysis_counter,int analysis_type){{{1*/
     2154void Tria::Update(int index, IoModel* iomodel,int analysis_counter,int analysis_type){ //i is the element index
     2155
     2156        /*Intermediaries*/
     2157        int    i;
     2158        int    tria_node_ids[3];
     2159        int    tria_vertex_ids[3];
     2160        double nodeinputs[3];
     2161
     2162        /*Checks if debuging*/
     2163        /*{{{2*/
     2164        ISSMASSERT(iomodel->elements);
     2165        /*}}}*/
     2166
     2167        /*Recover vertices ids needed to initialize inputs*/
     2168        for(i=0;i<3;i++){
     2169                tria_vertex_ids[i]=(int)iomodel->elements[3*index+i]; //ids for vertices are in the elements array from Matlab
     2170        }
     2171
     2172        /*Recover nodes ids needed to initialize the node hook.*/
     2173        if (analysis_type==Prognostic2AnalysisEnum || analysis_type==Balancedthickness2AnalysisEnum){
     2174                /*Discontinuous Galerkin*/
     2175                tria_node_ids[0]=iomodel->nodecounter+3*index+1;
     2176                tria_node_ids[1]=iomodel->nodecounter+3*index+2;
     2177                tria_node_ids[2]=iomodel->nodecounter+3*index+3;
     2178        }
     2179        else{
     2180                /*Continuous Galerkin*/
     2181                for(i=0;i<3;i++){
     2182                        tria_node_ids[i]=iomodel->nodecounter+(int)*(iomodel->elements+3*index+i); //ids for vertices are in the elements array from Matlab
     2183                }
     2184        }
     2185
     2186        /*hooks: */
     2187        this->SetHookNodes(tria_node_ids,analysis_counter); this->nodes=NULL; //set hook to nodes, for this analysis type
     2188       
     2189        /*add as many inputs per element as requested:*/
     2190        if (iomodel->thickness) {
     2191                for(i=0;i<3;i++)nodeinputs[i]=iomodel->thickness[tria_vertex_ids[i]-1];
     2192                this->inputs->AddInput(new TriaVertexInput(ThicknessEnum,nodeinputs));
     2193        }
     2194        if (iomodel->surface) {
     2195                for(i=0;i<3;i++)nodeinputs[i]=iomodel->surface[tria_vertex_ids[i]-1];
     2196                this->inputs->AddInput(new TriaVertexInput(SurfaceEnum,nodeinputs));
     2197        }
     2198        if (iomodel->bed) {
     2199                for(i=0;i<3;i++)nodeinputs[i]=iomodel->bed[tria_vertex_ids[i]-1];
     2200                this->inputs->AddInput(new TriaVertexInput(BedEnum,nodeinputs));
     2201        }
     2202        if (iomodel->drag_coefficient) {
     2203                for(i=0;i<3;i++)nodeinputs[i]=iomodel->drag_coefficient[tria_vertex_ids[i]-1];
     2204                this->inputs->AddInput(new TriaVertexInput(DragCoefficientEnum,nodeinputs));
     2205
     2206                if (iomodel->drag_p) this->inputs->AddInput(new DoubleInput(DragPEnum,iomodel->drag_p[index]));
     2207                if (iomodel->drag_q) this->inputs->AddInput(new DoubleInput(DragQEnum,iomodel->drag_q[index]));
     2208                this->inputs->AddInput(new IntInput(DragTypeEnum,iomodel->drag_type));
     2209        }
     2210        if (iomodel->melting_rate) {
     2211                for(i=0;i<3;i++)nodeinputs[i]=iomodel->melting_rate[tria_vertex_ids[i]-1]/iomodel->yts;
     2212                this->inputs->AddInput(new TriaVertexInput(MeltingRateEnum,nodeinputs));
     2213        }
     2214        if (iomodel->accumulation_rate) {
     2215                for(i=0;i<3;i++)nodeinputs[i]=iomodel->accumulation_rate[tria_vertex_ids[i]-1]/iomodel->yts;
     2216                this->inputs->AddInput(new TriaVertexInput(AccumulationRateEnum,nodeinputs));
     2217        }
     2218        if (iomodel->geothermalflux) {
     2219                for(i=0;i<3;i++)nodeinputs[i]=iomodel->geothermalflux[tria_vertex_ids[i]-1];
     2220                this->inputs->AddInput(new TriaVertexInput(GeothermalFluxEnum,nodeinputs));
     2221        }
     2222        if (iomodel->dhdt) {
     2223                for(i=0;i<3;i++)nodeinputs[i]=iomodel->dhdt[tria_vertex_ids[i]-1];
     2224                this->inputs->AddInput(new TriaVertexInput(DhDtEnum,nodeinputs));
     2225        }
     2226        if (iomodel->pressure) {
     2227                for(i=0;i<3;i++)nodeinputs[i]=iomodel->pressure[tria_vertex_ids[i]-1];
     2228                this->inputs->AddInput(new TriaVertexInput(PressureEnum,nodeinputs));
     2229        }
     2230        if (iomodel->temperature) {
     2231                for(i=0;i<3;i++)nodeinputs[i]=iomodel->temperature[tria_vertex_ids[i]-1];
     2232                this->inputs->AddInput(new TriaVertexInput(TemperatureEnum,nodeinputs));
     2233        }
     2234        /*vx,vy and vz: */
     2235        if (iomodel->vx) {
     2236                for(i=0;i<3;i++)nodeinputs[i]=iomodel->vx[tria_vertex_ids[i]-1]/iomodel->yts;
     2237                this->inputs->AddInput(new TriaVertexInput(VxEnum,nodeinputs));
     2238                this->inputs->AddInput(new TriaVertexInput(VxOldEnum,nodeinputs));
     2239        }
     2240        if (iomodel->vy) {
     2241                for(i=0;i<3;i++)nodeinputs[i]=iomodel->vy[tria_vertex_ids[i]-1]/iomodel->yts;
     2242                this->inputs->AddInput(new TriaVertexInput(VyEnum,nodeinputs));
     2243                this->inputs->AddInput(new TriaVertexInput(VyOldEnum,nodeinputs));
     2244        }
     2245        if (iomodel->vz) {
     2246                for(i=0;i<3;i++)nodeinputs[i]=iomodel->vz[tria_vertex_ids[i]-1]/iomodel->yts;
     2247                this->inputs->AddInput(new TriaVertexInput(VzEnum,nodeinputs));
     2248                this->inputs->AddInput(new TriaVertexInput(VzOldEnum,nodeinputs));
     2249        }
     2250        if (iomodel->vx_obs) {
     2251                for(i=0;i<3;i++)nodeinputs[i]=iomodel->vx_obs[tria_vertex_ids[i]-1]/iomodel->yts;
     2252                this->inputs->AddInput(new TriaVertexInput(VxObsEnum,nodeinputs));
     2253        }
     2254        if (iomodel->vy_obs) {
     2255                for(i=0;i<3;i++)nodeinputs[i]=iomodel->vy_obs[tria_vertex_ids[i]-1]/iomodel->yts;
     2256                this->inputs->AddInput(new TriaVertexInput(VyObsEnum,nodeinputs));
     2257        }
     2258        if (iomodel->vz_obs) {
     2259                for(i=0;i<3;i++)nodeinputs[i]=iomodel->vz_obs[tria_vertex_ids[i]-1]/iomodel->yts;
     2260                this->inputs->AddInput(new TriaVertexInput(VzObsEnum,nodeinputs));
     2261        }
     2262        if (iomodel->weights) {
     2263                for(i=0;i<3;i++)nodeinputs[i]=iomodel->weights[tria_vertex_ids[i]-1];
     2264                this->inputs->AddInput(new TriaVertexInput(WeightsEnum,nodeinputs));
     2265        }
     2266        if (iomodel->elementoniceshelf) this->inputs->AddInput(new BoolInput(ElementOnIceShelfEnum,(IssmBool)iomodel->elementoniceshelf[index]));
     2267        if (iomodel->elementonbed) this->inputs->AddInput(new BoolInput(ElementOnBedEnum,(IssmBool)iomodel->elementonbed[index]));
     2268        if (iomodel->elementonwater) this->inputs->AddInput(new BoolInput(ElementOnWaterEnum,(IssmBool)iomodel->elementonwater[index]));
     2269        if (iomodel->elementonsurface) this->inputs->AddInput(new BoolInput(ElementOnSurfaceEnum,(IssmBool)iomodel->elementonsurface[index]));
     2270
     2271        /*Defaults if not provided in iomodel*/
     2272        switch(analysis_type){
     2273
     2274                case DiagnosticHorizAnalysisEnum: case DiagnosticVertAnalysisEnum: case DiagnosticStokesAnalysisEnum:
     2275
     2276                        /*default vx,vy and vz: either observation or 0 */
     2277                        if(!iomodel->vx){
     2278                                if (iomodel->vx_obs) for(i=0;i<3;i++)nodeinputs[i]=iomodel->vx_obs[tria_vertex_ids[i]-1]/iomodel->yts;
     2279                                else                 for(i=0;i<3;i++)nodeinputs[i]=0;
     2280                                this->inputs->AddInput(new TriaVertexInput(VxEnum,nodeinputs));
     2281                                this->inputs->AddInput(new TriaVertexInput(VxOldEnum,nodeinputs));
     2282                        }
     2283                        if(!iomodel->vy){
     2284                                if (iomodel->vy_obs) for(i=0;i<3;i++)nodeinputs[i]=iomodel->vy_obs[tria_vertex_ids[i]-1]/iomodel->yts;
     2285                                else                 for(i=0;i<3;i++)nodeinputs[i]=0;
     2286                                this->inputs->AddInput(new TriaVertexInput(VyEnum,nodeinputs));
     2287                                this->inputs->AddInput(new TriaVertexInput(VyOldEnum,nodeinputs));
     2288                        }
     2289                        if(!iomodel->vz){
     2290                                if (iomodel->vz_obs) for(i=0;i<3;i++)nodeinputs[i]=iomodel->vz_obs[tria_vertex_ids[i]-1]/iomodel->yts;
     2291                                else                 for(i=0;i<3;i++)nodeinputs[i]=0;
     2292                                this->inputs->AddInput(new TriaVertexInput(VzEnum,nodeinputs));
     2293                                this->inputs->AddInput(new TriaVertexInput(VzOldEnum,nodeinputs));
     2294                        }
     2295                        break;
     2296
     2297                default:
     2298                        /*No update for other solution types*/
     2299                        break;
     2300
     2301        }
     2302
     2303        //this->parameters: we still can't point to it, it may not even exist. Configure will handle this.
     2304        this->parameters=NULL;
     2305
     2306}
     2307/*}}}*/
     2308/*FUNCTION Tria::UpdateGeometry{{{1*/
     2309void  Tria::UpdateGeometry(void){
     2310
     2311        /*Intermediaries*/
     2312        double rho_ice,rho_water;
     2313
     2314        /*If shelf: hydrostatic equilibrium*/
     2315        if (this->GetShelf()){
     2316
     2317                /*recover material parameters: */
     2318                rho_ice=matpar->GetRhoIce();
     2319                rho_water=matpar->GetRhoWater();
     2320
     2321                /*Create New Surface: s = (1-rho_ice/rho_water) h*/
     2322                InputDuplicate(ThicknessEnum,SurfaceEnum);     //1: copy thickness into surface
     2323                InputScale(SurfaceEnum,(1-rho_ice/rho_water)); //2: surface = surface * (1-di)
     2324
     2325                /*Create New Bed b = -rho_ice/rho_water h*/
     2326                InputDuplicate(ThicknessEnum,BedEnum);         //1: copy thickness into bed
     2327                InputScale(BedEnum, -rho_ice/rho_water);       //2: bed = bed * (-di)
     2328        }
     2329
     2330        /*If sheet: surface = bed + thickness*/
     2331        else{
     2332
     2333                /*The bed does not change, update surface only s = b + h*/
     2334                InputDuplicate(BedEnum,SurfaceEnum);          //1: copy bed into surface
     2335                InputAXPY(SurfaceEnum,1.0,ThicknessEnum);     //2: surface = surface + 1 * thickness
     2336        }
     2337
     2338}
     2339/*}}}*/
     2340
     2341
     2342/*Tria specific routines: */
     2343/*FUNCTION Tria::CreateKMatrixBalancedthickness {{{1*/
     2344void  Tria::CreateKMatrixBalancedthickness(Mat Kgg){
     2345
     2346        /* local declarations */
     2347        int             i,j;
     2348
     2349        /* node data: */
     2350        const int    numgrids=3;
     2351        const int    NDOF1=1;
     2352        const int    numdof=NDOF1*numgrids;
     2353        double       xyz_list[numgrids][3];
     2354        int          doflist[numdof];
     2355        int          numberofdofspernode;
     2356
     2357        /* gaussian points: */
     2358        int     num_gauss,ig;
     2359        double* first_gauss_area_coord  =  NULL;
     2360        double* second_gauss_area_coord =  NULL;
     2361        double* third_gauss_area_coord  =  NULL;
     2362        double* gauss_weights           =  NULL;
     2363        double  gauss_weight;
     2364        double  gauss_l1l2l3[3];
     2365
     2366        /* matrices: */
     2367        double L[numgrids];
     2368        double B[2][numgrids];
     2369        double Bprime[2][numgrids];
     2370        double DL[2][2]={0.0};
     2371        double DLprime[2][2]={0.0};
     2372        double DL_scalar;
     2373        double Ke_gg[numdof][numdof]={0.0};//local element stiffness matrix
     2374        double Ke_gg_gaussian[numdof][numdof]={0.0}; //stiffness matrix evaluated at the gaussian point.
     2375        double Ke_gg_thickness1[numdof][numdof]={0.0}; //stiffness matrix evaluated at the gaussian point.
     2376        double Ke_gg_thickness2[numdof][numdof]={0.0}; //stiffness matrix evaluated at the gaussian point.
     2377
     2378        double Jdettria;
     2379
     2380        /*input parameters for structural analysis (diagnostic): */
     2381        double  dvx[2];
     2382        double  dvy[2];
     2383        double  vx,vy;
     2384        double  dvxdx,dvydy;
     2385        double  v_gauss[2]={0.0};
     2386
     2387
     2388        double  K[2][2]={0.0};
     2389        double  KDL[2][2]={0.0};
     2390        int     dofs[2]={0,1};
     2391        int     found=0;
     2392
     2393        /*parameters: */
     2394        bool artdiff;
     2395
     2396        /* Get node coordinates and dof list: */
     2397        GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
     2398        GetDofList(&doflist[0],&numberofdofspernode);
     2399
     2400        /*retrieve some parameters: */
     2401        this->parameters->FindParam(&artdiff,ArtDiffEnum);
     2402
     2403        //Create Artificial diffusivity once for all if requested
     2404        if(artdiff){
     2405                //Get the Jacobian determinant
     2406                gauss_l1l2l3[0]=ONETHIRD; gauss_l1l2l3[1]=ONETHIRD; gauss_l1l2l3[2]=ONETHIRD;
     2407                GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss_l1l2l3);
     2408
     2409                //Build K matrix (artificial diffusivity matrix)
     2410                inputs->GetParameterAverage(&v_gauss[0],VxAverageEnum);
     2411                inputs->GetParameterAverage(&v_gauss[1],VyAverageEnum);
     2412
     2413                K[0][0]=pow(Jdettria,(double).5)/2.0*fabs(v_gauss[0]);
     2414                K[1][1]=pow(Jdettria,(double).5)/2.0*fabs(v_gauss[1]);
     2415        }
     2416
     2417        /* Get gaussian points and weights (make this a statically initialized list of points? fstd): */
     2418        GaussTria( &num_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &gauss_weights, 2);
     2419
     2420        /* Start  looping on the number of gaussian points: */
     2421        for (ig=0; ig<num_gauss; ig++){
     2422                /*Pick up the gaussian point: */
     2423                gauss_weight=*(gauss_weights+ig);
     2424                gauss_l1l2l3[0]=*(first_gauss_area_coord+ig);
     2425                gauss_l1l2l3[1]=*(second_gauss_area_coord+ig);
     2426                gauss_l1l2l3[2]=*(third_gauss_area_coord+ig);
     2427
     2428                /* Get Jacobian determinant: */
     2429                GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss_l1l2l3);
     2430
     2431                /*Get B  and B prime matrix: */
     2432                GetB_prog(&B[0][0], &xyz_list[0][0], gauss_l1l2l3);
     2433                GetBPrime_prog(&Bprime[0][0], &xyz_list[0][0], gauss_l1l2l3);
     2434
     2435                //Get vx, vy and their derivatives at gauss point
     2436                inputs->GetParameterValue(&vx, &gauss_l1l2l3[0],VxAverageEnum);
     2437                inputs->GetParameterValue(&vy, &gauss_l1l2l3[0],VyAverageEnum);
     2438
     2439                inputs->GetParameterDerivativeValue(&dvx[0],&xyz_list[0][0],&gauss_l1l2l3[0],VxAverageEnum);
     2440                inputs->GetParameterDerivativeValue(&dvy[0],&xyz_list[0][0],&gauss_l1l2l3[0],VyAverageEnum);
     2441
     2442                dvxdx=dvx[0];
     2443                dvydy=dvy[1];
     2444
     2445                DL_scalar=gauss_weight*Jdettria;
     2446
     2447                //Create DL and DLprime matrix
     2448                DL[0][0]=DL_scalar*dvxdx;
     2449                DL[1][1]=DL_scalar*dvydy;
     2450
     2451                DLprime[0][0]=DL_scalar*vx;
     2452                DLprime[1][1]=DL_scalar*vy;
     2453
     2454                //Do the triple product tL*D*L.
     2455                //Ke_gg_thickness=B'*DLprime*Bprime;
     2456
     2457                TripleMultiply( &B[0][0],2,numdof,1,
     2458                                        &DL[0][0],2,2,0,
     2459                                        &B[0][0],2,numdof,0,
     2460                                        &Ke_gg_thickness1[0][0],0);
     2461
     2462                TripleMultiply( &B[0][0],2,numdof,1,
     2463                                        &DLprime[0][0],2,2,0,
     2464                                        &Bprime[0][0],2,numdof,0,
     2465                                        &Ke_gg_thickness2[0][0],0);
     2466
     2467                /* Add the Ke_gg_gaussian, and optionally Ke_gg_drag_gaussian onto Ke_gg: */
     2468                for( i=0; i<numdof; i++) for(j=0;j<numdof;j++) Ke_gg[i][j]+=Ke_gg_thickness1[i][j];
     2469                for( i=0; i<numdof; i++) for(j=0;j<numdof;j++) Ke_gg[i][j]+=Ke_gg_thickness2[i][j];
     2470
     2471                if(artdiff){
     2472
     2473                        /* Compute artificial diffusivity */
     2474                        KDL[0][0]=DL_scalar*K[0][0];
     2475                        KDL[1][1]=DL_scalar*K[1][1];
     2476
     2477                        TripleMultiply( &Bprime[0][0],2,numdof,1,
     2478                                                &KDL[0][0],2,2,0,
     2479                                                &Bprime[0][0],2,numdof,0,
     2480                                                &Ke_gg_gaussian[0][0],0);
     2481
     2482                        /* Add artificial diffusivity matrix */
     2483                        for( i=0; i<numdof; i++) for(j=0;j<numdof;j++) Ke_gg[i][j]+=Ke_gg_gaussian[i][j];
     2484
     2485                }
     2486        } // for (ig=0; ig<num_gauss; ig++)
     2487
     2488        /*Add Ke_gg to global matrix Kgg: */
     2489        MatSetValues(Kgg,numdof,doflist,numdof,doflist,(const double*)Ke_gg,ADD_VALUES);
     2490
     2491cleanup_and_return:
     2492        xfree((void**)&first_gauss_area_coord);
     2493        xfree((void**)&second_gauss_area_coord);
     2494        xfree((void**)&third_gauss_area_coord);
     2495        xfree((void**)&gauss_weights);
     2496
     2497}
     2498/*}}}*/
     2499/*FUNCTION Tria::CreateKMatrixBalancedthickness2 {{{1*/
     2500void  Tria::CreateKMatrixBalancedthickness2(Mat Kgg){
     2501
     2502        /* local declarations */
     2503        int             i,j;
     2504
     2505        /* node data: */
     2506        const int    numgrids=3;
     2507        const int    NDOF1=1;
     2508        const int    numdof=NDOF1*numgrids;
     2509        double       xyz_list[numgrids][3];
     2510        int          doflist[numdof];
     2511        int          numberofdofspernode;
     2512
     2513        /* gaussian points: */
     2514        int     num_gauss,ig;
     2515        double* first_gauss_area_coord  =  NULL;
     2516        double* second_gauss_area_coord =  NULL;
     2517        double* third_gauss_area_coord  =  NULL;
     2518        double* gauss_weights           =  NULL;
     2519        double  gauss_weight;
     2520        double  gauss_l1l2l3[3];
     2521
     2522        /* matrices: */
     2523        double B[2][numgrids];
     2524        double Bprime[2][numgrids];
     2525        double DL[2][2]={0.0};
     2526        double DLprime[2][2]={0.0};
     2527        double DL_scalar;
     2528        double Ke_gg[numdof][numdof]={0.0};
     2529        double Ke_gg2[numdof][numdof]={0.0};
     2530        double Jdettria;
     2531
     2532        /*input parameters for structural analysis (diagnostic): */
     2533        double  vx,vy;
     2534        int     dofs[1]={0};
     2535        int     found;
     2536
     2537        /* Get node coordinates and dof list: */
     2538        GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
     2539        GetDofList(&doflist[0],&numberofdofspernode);
     2540
     2541        /* Get gaussian points and weights (make this a statically initialized list of points? fstd): */
     2542        GaussTria( &num_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &gauss_weights, 2);
     2543
     2544        /* Start  looping on the number of gaussian points: */
     2545        for (ig=0; ig<num_gauss; ig++){
     2546                /*Pick up the gaussian point: */
     2547                gauss_weight=*(gauss_weights+ig);
     2548                gauss_l1l2l3[0]=*(first_gauss_area_coord+ig);
     2549                gauss_l1l2l3[1]=*(second_gauss_area_coord+ig);
     2550                gauss_l1l2l3[2]=*(third_gauss_area_coord+ig);
     2551
     2552                /* Get Jacobian determinant: */
     2553                GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss_l1l2l3);
     2554
     2555                /*Get B  and B prime matrix: */
     2556                /*WARNING: B and Bprime are inverted compared to usual prognostic!!!!*/
     2557                GetB_prog(&Bprime[0][0], &xyz_list[0][0], gauss_l1l2l3);
     2558                GetBPrime_prog(&B[0][0], &xyz_list[0][0], gauss_l1l2l3);
     2559
     2560                //Get vx, vy and their derivatives at gauss point
     2561                inputs->GetParameterValue(&vx, &gauss_l1l2l3[0],VxEnum);
     2562                inputs->GetParameterValue(&vy, &gauss_l1l2l3[0],VyEnum);
     2563
     2564                DL_scalar=-gauss_weight*Jdettria;
     2565
     2566                DLprime[0][0]=DL_scalar*vx;
     2567                DLprime[1][1]=DL_scalar*vy;
     2568
     2569                //Do the triple product tL*D*L.
     2570                TripleMultiply( &B[0][0],2,numdof,1,
     2571                                        &DLprime[0][0],2,2,0,
     2572                                        &Bprime[0][0],2,numdof,0,
     2573                                        &Ke_gg2[0][0],0);
     2574
     2575                /* Add the Ke_gg_gaussian, and optionally Ke_gg_drag_gaussian onto Ke_gg: */
     2576                for( i=0; i<numdof; i++) for(j=0;j<numdof;j++) Ke_gg[i][j]+=Ke_gg2[i][j];
     2577
     2578        } // for (ig=0; ig<num_gauss; ig++)
     2579
     2580        /*Add Ke_gg to global matrix Kgg: */
     2581        MatSetValues(Kgg,numdof,doflist,numdof,doflist,(const double*)Ke_gg,ADD_VALUES);
     2582
     2583cleanup_and_return:
     2584        xfree((void**)&first_gauss_area_coord);
     2585        xfree((void**)&second_gauss_area_coord);
     2586        xfree((void**)&third_gauss_area_coord);
     2587        xfree((void**)&gauss_weights);
     2588
     2589}
     2590/*}}}*/
     2591/*FUNCTION Tria::CreateKMatrixBalancedvelocities {{{1*/
     2592void  Tria::CreateKMatrixBalancedvelocities(Mat Kgg){
     2593
     2594        /* local declarations */
     2595        int             i,j;
     2596
     2597        /* node data: */
     2598        const int    numgrids=3;
     2599        const int    NDOF1=1;
     2600        const int    numdof=NDOF1*numgrids;
     2601        double       xyz_list[numgrids][3];
     2602        int          doflist[numdof];
     2603        int          numberofdofspernode;
     2604        double  gaussgrids[numgrids][numgrids]={{1,0,0},{0,1,0},{0,0,1}};
     2605
     2606        /* gaussian points: */
     2607        int     num_gauss,ig;
     2608        double* first_gauss_area_coord  =  NULL;
     2609        double* second_gauss_area_coord =  NULL;
     2610        double* third_gauss_area_coord  =  NULL;
     2611        double* gauss_weights           =  NULL;
     2612        double  gauss_weight;
     2613        double  gauss_l1l2l3[3];
     2614
     2615        /* matrices: */
     2616        double L[numgrids];
     2617        double B[2][numgrids];
     2618        double Bprime[2][numgrids];
     2619        double DL[2][2]={0.0};
     2620        double DLprime[2][2]={0.0};
     2621        double DL_scalar;
     2622        double Ke_gg[numdof][numdof]={0.0};//local element stiffness matrix
     2623        double Ke_gg_gaussian[numdof][numdof]={0.0}; //stiffness matrix evaluated at the gaussian point.
     2624        double Ke_gg_velocities1[numdof][numdof]={0.0}; //stiffness matrix evaluated at the gaussian point.
     2625        double Ke_gg_velocities2[numdof][numdof]={0.0}; //stiffness matrix evaluated at the gaussian point.
     2626        double Jdettria;
     2627
     2628        /*input parameters for structural analysis (diagnostic): */
     2629        double  surface_normal[3];
     2630        double  surface_list[3];
     2631        double  nx,ny,norm;
     2632        double  dvx[2];
     2633        double  dvy[2];
     2634        double  vx,vy;
     2635        double  dvxdx,dvydy;
     2636        double  v_gauss[2]={0.0};
     2637        double  K[2][2]={0.0};
     2638        double  KDL[2][2]={0.0};
     2639        int     dofs[2]={0,1};
     2640        int     found=0;
     2641
     2642        /*parameters: */
     2643        bool artdiff;
     2644
     2645        /*retrieve some parameters: */
     2646        this->parameters->FindParam(&artdiff,ArtDiffEnum);
     2647
     2648        /* Get node coordinates and dof list: */
     2649        GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
     2650        GetDofList(&doflist[0],&numberofdofspernode);
     2651
     2652        /*Modify z so that it reflects the surface*/
     2653        inputs->GetParameterValues(&surface_list[0],&gaussgrids[0][0],3,SurfaceEnum);
     2654        for(i=0;i<numgrids;i++) xyz_list[i][2]=surface_list[i];
     2655
     2656        /*Get normal vector to the surface*/
     2657        inputs->GetParameterAverage(&nx,VxAverageEnum);
     2658        inputs->GetParameterAverage(&ny,VyAverageEnum);
     2659        if(nx==0 && ny==0){
     2660                SurfaceNormal(&surface_normal[0],xyz_list);
     2661                nx=surface_normal[0];
     2662                ny=surface_normal[1];
     2663        }
     2664        if(nx==0 && ny==0){
     2665                nx=0;
     2666                ny=1;
     2667        }
     2668        norm=pow( pow(nx,2)+pow(ny,2) , (double).5);
     2669        nx=nx/norm;
     2670        ny=ny/norm;
     2671
     2672        //Create Artificial diffusivity once for all if requested
     2673        if(artdiff){
     2674                //Get the Jacobian determinant
     2675                gauss_l1l2l3[0]=ONETHIRD; gauss_l1l2l3[1]=ONETHIRD; gauss_l1l2l3[2]=ONETHIRD;
     2676                GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss_l1l2l3);
     2677
     2678                //Build K matrix (artificial diffusivity matrix)
     2679                inputs->GetParameterAverage(&v_gauss[0],VxAverageEnum);
     2680                inputs->GetParameterAverage(&v_gauss[1],VyAverageEnum);
     2681
     2682                K[0][0]=pow(10,2)*pow(Jdettria,(double).5)/2.0*fabs(v_gauss[0]); //pow should be zero!!
     2683                K[1][1]=pow(10,2)*pow(Jdettria,(double).5)/2.0*fabs(v_gauss[1]);
     2684        }
     2685
     2686        /* Get gaussian points and weights (make this a statically initialized list of points? fstd): */
     2687        GaussTria( &num_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &gauss_weights, 2);
     2688
     2689        /* Start  looping on the number of gaussian points: */
     2690        for (ig=0; ig<num_gauss; ig++){
     2691                /*Pick up the gaussian point: */
     2692                gauss_weight=*(gauss_weights+ig);
     2693                gauss_l1l2l3[0]=*(first_gauss_area_coord+ig);
     2694                gauss_l1l2l3[1]=*(second_gauss_area_coord+ig);
     2695                gauss_l1l2l3[2]=*(third_gauss_area_coord+ig);
     2696
     2697                /* Get Jacobian determinant: */
     2698                GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss_l1l2l3);
     2699
     2700                /*Get B  and B prime matrix: */
     2701                GetB_prog(&B[0][0], &xyz_list[0][0], gauss_l1l2l3);
     2702                GetBPrime_prog(&Bprime[0][0], &xyz_list[0][0], gauss_l1l2l3);
     2703
     2704                //Get vx, vy and their derivatives at gauss point
     2705                inputs->GetParameterValue(&vx,&gauss_l1l2l3[0],VxAverageEnum);
     2706                inputs->GetParameterValue(&vy,&gauss_l1l2l3[0],VyAverageEnum);
     2707
     2708                inputs->GetParameterDerivativeValue(&dvx[0],&xyz_list[0][0],&gauss_l1l2l3[0],VxAverageEnum);
     2709                inputs->GetParameterDerivativeValue(&dvy[0],&xyz_list[0][0],&gauss_l1l2l3[0],VyAverageEnum);
     2710
     2711                dvxdx=dvx[0];
     2712                dvydy=dvy[1];
     2713
     2714                DL_scalar=gauss_weight*Jdettria;
     2715
     2716                DLprime[0][0]=DL_scalar*nx;
     2717                DLprime[1][1]=DL_scalar*ny;
     2718
     2719                //Do the triple product tL*D*L.
     2720                //Ke_gg_velocities=B'*DLprime*Bprime;
     2721                TripleMultiply( &B[0][0],2,numdof,1,
     2722                                        &DLprime[0][0],2,2,0,
     2723                                        &Bprime[0][0],2,numdof,0,
     2724                                        &Ke_gg_velocities2[0][0],0);
     2725
     2726                /* Add the Ke_gg_gaussian, and optionally Ke_gg_drag_gaussian onto Ke_gg: */
     2727                for( i=0; i<numdof; i++) for(j=0;j<numdof;j++) Ke_gg[i][j]+=Ke_gg_velocities2[i][j];
     2728
     2729                if(artdiff){
     2730
     2731                        /* Compute artificial diffusivity */
     2732                        KDL[0][0]=DL_scalar*K[0][0];
     2733                        KDL[1][1]=DL_scalar*K[1][1];
     2734
     2735                        TripleMultiply( &Bprime[0][0],2,numdof,1,
     2736                                                &KDL[0][0],2,2,0,
     2737                                                &Bprime[0][0],2,numdof,0,
     2738                                                &Ke_gg_gaussian[0][0],0);
     2739
     2740                        /* Add artificial diffusivity matrix */
     2741                        for( i=0; i<numdof; i++) for(j=0;j<numdof;j++) Ke_gg[i][j]+=Ke_gg_gaussian[i][j];
     2742
     2743                }
     2744
     2745        } // for (ig=0; ig<num_gauss; ig++)
     2746
     2747        /*Add Ke_gg to global matrix Kgg: */
     2748        MatSetValues(Kgg,numdof,doflist,numdof,doflist,(const double*)Ke_gg,ADD_VALUES);
     2749
     2750
     2751cleanup_and_return:
     2752        xfree((void**)&first_gauss_area_coord);
     2753        xfree((void**)&second_gauss_area_coord);
     2754        xfree((void**)&third_gauss_area_coord);
     2755        xfree((void**)&gauss_weights);
     2756
     2757}
     2758/*}}}*/
     2759/*FUNCTION Tria::CreateKMatrixDiagnosticHoriz {{{1*/
     2760void  Tria::CreateKMatrixDiagnosticHoriz(Mat Kgg){
     2761
     2762        /* local declarations */
     2763        int             i,j;
     2764
     2765        /* node data: */
     2766        const int    numgrids=3;
     2767        const int    numdof=2*numgrids;
     2768        double       xyz_list[numgrids][3];
     2769        int          doflist[numdof];
     2770        int          numberofdofspernode;
     2771
     2772        /* gaussian points: */
     2773        int     num_gauss,ig;
     2774        double* first_gauss_area_coord  =  NULL;
     2775        double* second_gauss_area_coord =  NULL;
     2776        double* third_gauss_area_coord  =  NULL;
     2777        double* gauss_weights           =  NULL;
     2778        double  gauss_weight;
     2779        double  gauss_l1l2l3[3];
     2780
     2781        /* material data: */
     2782        double viscosity; //viscosity
     2783        double newviscosity; //viscosity
     2784        double oldviscosity; //viscosity
     2785
     2786        /* strain rate: */
     2787        double epsilon[3]; /* epsilon=[exx,eyy,exy];*/
     2788        double oldepsilon[3]; /* oldepsilon=[exx,eyy,exy];*/
     2789
     2790        /* matrices: */
     2791        double B[3][numdof];
     2792        double Bprime[3][numdof];
     2793        double D[3][3]={0.0};  // material matrix, simple scalar matrix.
     2794        double D_scalar;
     2795
     2796        /*parameters: */
     2797        double viscosity_overshoot;
     2798
     2799        /* local element matrices: */
     2800        double Ke_gg[numdof][numdof]={0.0};
     2801        double Ke_gg_gaussian[numdof][numdof]; //stiffness matrix evaluated at the gaussian point.
     2802
     2803        double Jdet;
     2804
     2805        /*input parameters for structural analysis (diagnostic): */
     2806        double  thickness;
     2807        int     dofs[2]={0,1};
     2808
     2809        /*inputs: */
     2810        bool onwater,shelf;
     2811
     2812        /*retrieve inputs :*/
     2813        inputs->GetParameterValue(&onwater,ElementOnWaterEnum);
     2814        inputs->GetParameterValue(&shelf,ElementOnIceShelfEnum);
     2815
     2816        /*retrieve some parameters: */
     2817        this->parameters->FindParam(&viscosity_overshoot,ViscosityOvershootEnum);
     2818
     2819        /*First, if we are on water, return empty matrix: */
     2820        if(onwater) return;
     2821
     2822        /* Get node coordinates and dof list: */
     2823        GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
     2824        GetDofList(&doflist[0],&numberofdofspernode);
     2825
     2826        /* Get gaussian points and weights (make this a statically initialized list of points? fstd): */
     2827        GaussTria( &num_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &gauss_weights, 2);
     2828
     2829        /* Start  looping on the number of gaussian points: */
     2830        for (ig=0; ig<num_gauss; ig++){
     2831                /*Pick up the gaussian point: */
     2832                gauss_weight=*(gauss_weights+ig);
     2833                gauss_l1l2l3[0]=*(first_gauss_area_coord+ig);
     2834                gauss_l1l2l3[1]=*(second_gauss_area_coord+ig);
     2835                gauss_l1l2l3[2]=*(third_gauss_area_coord+ig);
     2836
     2837
     2838                /*Compute thickness at gaussian point: */
     2839                inputs->GetParameterValue(&thickness, gauss_l1l2l3,ThicknessEnum);
     2840
     2841                /*Get strain rate from velocity: */
     2842                inputs->GetStrainRate2d(&epsilon[0],&xyz_list[0][0],gauss_l1l2l3,VxEnum,VyEnum);
     2843                inputs->GetStrainRate2d(&oldepsilon[0],&xyz_list[0][0],gauss_l1l2l3,VxOldEnum,VyOldEnum);
     2844
     2845                /*Get viscosity: */
     2846                matice->GetViscosity2d(&viscosity, &epsilon[0]);
     2847                matice->GetViscosity2d(&oldviscosity, &oldepsilon[0]);
     2848
     2849                /* Get Jacobian determinant: */
     2850                GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0],gauss_l1l2l3);
     2851
     2852                /* Build the D matrix: we plug the gaussian weight, the thickness, the viscosity, and the jacobian determinant
     2853                        onto this scalar matrix, so that we win some computational time: */
     2854                newviscosity=viscosity+viscosity_overshoot*(viscosity-oldviscosity);
     2855                D_scalar=newviscosity*thickness*gauss_weight*Jdet;
     2856
     2857                for (i=0;i<3;i++){
     2858                        D[i][i]=D_scalar;
     2859                }
     2860
     2861                /*Get B and Bprime matrices: */
     2862                GetB(&B[0][0], &xyz_list[0][0], gauss_l1l2l3);
     2863                GetBPrime(&Bprime[0][0], &xyz_list[0][0], gauss_l1l2l3);
     2864
     2865                /*  Do the triple product tB*D*Bprime: */
     2866                TripleMultiply( &B[0][0],3,numdof,1,
     2867                                        &D[0][0],3,3,0,
     2868                                        &Bprime[0][0],3,numdof,0,
     2869                                        &Ke_gg_gaussian[0][0],0);
     2870
     2871                /* Add the Ke_gg_gaussian, and optionally Ke_gg_drag_gaussian onto Ke_gg: */
     2872                for( i=0; i<numdof; i++) for(j=0;j<numdof;j++) Ke_gg[i][j]+=Ke_gg_gaussian[i][j];
     2873
     2874        } // for (ig=0; ig<num_gauss; ig++)
     2875
     2876        /*Add Ke_gg to global matrix Kgg: */
     2877        MatSetValues(Kgg,numdof,doflist,numdof,doflist,(const double*)Ke_gg,ADD_VALUES);
     2878
     2879        /*Do not forget to include friction: */
     2880        if(!shelf){
     2881                CreateKMatrixDiagnosticHorizFriction(Kgg);
     2882        }
     2883
     2884cleanup_and_return:
     2885        xfree((void**)&first_gauss_area_coord);
     2886        xfree((void**)&second_gauss_area_coord);
     2887        xfree((void**)&third_gauss_area_coord);
     2888        xfree((void**)&gauss_weights);
     2889
     2890}
     2891/*}}}*/
     2892/*FUNCTION Tria::CreateKMatrixDiagnosticHorizFriction {{{1*/
     2893void  Tria::CreateKMatrixDiagnosticHorizFriction(Mat Kgg){
     2894
     2895
     2896        /* local declarations */
     2897        int             i,j;
     2898        int analysis_type;
     2899
     2900        /* node data: */
     2901        const int    numgrids=3;
     2902        const int    numdof=2*numgrids;
     2903        double       xyz_list[numgrids][3];
     2904        int          doflist[numdof];
     2905        int          numberofdofspernode;
     2906       
     2907        /* gaussian points: */
     2908        int     num_gauss,ig;
     2909        double* first_gauss_area_coord  =  NULL;
     2910        double* second_gauss_area_coord =  NULL;
     2911        double* third_gauss_area_coord  =  NULL;
     2912        double* gauss_weights           =  NULL;
     2913        double  gauss_weight;
     2914        double  gauss_l1l2l3[3];
     2915
     2916        /* matrices: */
     2917        double L[2][numdof];
     2918        double DL[2][2]={{ 0,0 },{0,0}}; //for basal drag
     2919        double DL_scalar;
     2920
     2921        /* local element matrices: */
     2922        double Ke_gg[numdof][numdof]={0.0};
     2923        double Ke_gg_gaussian[numdof][numdof]; //stiffness matrix contribution from drag
     2924       
     2925        double Jdet;
     2926       
     2927        /*slope: */
     2928        double  slope[2]={0.0,0.0};
     2929        double  slope_magnitude;
     2930
     2931        /*friction: */
     2932        Friction* friction=NULL;
     2933        double alpha2;
     2934
     2935        double MAXSLOPE=.06; // 6 %
     2936        double MOUNTAINKEXPONENT=10;
     2937
     2938        /*inputs: */
     2939        bool shelf;
     2940        int  drag_type;
     2941
     2942        /*retrive parameters: */
     2943        parameters->FindParam(&analysis_type,AnalysisTypeEnum);
     2944
     2945        /*retrieve inputs :*/
     2946        inputs->GetParameterValue(&shelf,ElementOnIceShelfEnum);
     2947        inputs->GetParameterValue(&drag_type,DragTypeEnum);
     2948       
     2949        /* Get node coordinates and dof list: */
     2950        GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
     2951        GetDofList(&doflist[0],&numberofdofspernode);
     2952
     2953        if (shelf){
     2954                /*no friction, do nothing*/
     2955                return;
     2956        }
     2957
     2958        /*build friction object, used later on: */
     2959        if (drag_type!=2)ISSMERROR(" non-viscous friction not supported yet!");
     2960        friction=new Friction("2d",inputs,matpar,analysis_type);
     2961
     2962        /* Get gaussian points and weights (make this a statically initialized list of points? fstd): */
     2963        GaussTria( &num_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &gauss_weights, 2);
     2964
     2965        /* Start  looping on the number of gaussian points: */
     2966        for (ig=0; ig<num_gauss; ig++){
     2967                /*Pick up the gaussian point: */
     2968                gauss_weight=*(gauss_weights+ig);
     2969                gauss_l1l2l3[0]=*(first_gauss_area_coord+ig);
     2970                gauss_l1l2l3[1]=*(second_gauss_area_coord+ig);
     2971                gauss_l1l2l3[2]=*(third_gauss_area_coord+ig);
     2972
     2973                /*Friction: */
     2974                friction->GetAlpha2(&alpha2, gauss_l1l2l3,VxEnum,VyEnum,VzEnum);
     2975
     2976                // If we have a slope > 6% for this element,  it means  we are on a mountain. In this particular case,
     2977                //velocity should be = 0. To achieve this result, we set alpha2_list to a very high value: */
     2978                inputs->GetParameterDerivativeValue(&slope[0],&xyz_list[0][0],&gauss_l1l2l3[0],SurfaceEnum);
     2979                slope_magnitude=sqrt(pow(slope[0],2)+pow(slope[1],2));
     2980
     2981                if (slope_magnitude>MAXSLOPE){
     2982                        alpha2=pow((double)10,MOUNTAINKEXPONENT);
     2983                }
     2984
     2985                /* Get Jacobian determinant: */
     2986                GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0],gauss_l1l2l3);
     2987
     2988                /*Get L matrix: */
     2989                GetL(&L[0][0], &xyz_list[0][0], gauss_l1l2l3,numberofdofspernode);
     2990
     2991               
     2992                DL_scalar=alpha2*gauss_weight*Jdet;
     2993                for (i=0;i<2;i++){
     2994                        DL[i][i]=DL_scalar;
     2995                }
     2996               
     2997                /*  Do the triple producte tL*D*L: */
     2998                TripleMultiply( &L[0][0],2,numdof,1,
     2999                                        &DL[0][0],2,2,0,
     3000                                        &L[0][0],2,numdof,0,
     3001                                        &Ke_gg_gaussian[0][0],0);
     3002
     3003                for( i=0; i<numdof; i++) for(j=0;j<numdof;j++) Ke_gg[i][j]+=Ke_gg_gaussian[i][j];
     3004
     3005        } // for (ig=0; ig<num_gauss; ig++)
     3006
     3007        /*Add Ke_gg to global matrix Kgg: */
     3008        MatSetValues(Kgg,numdof,doflist,numdof,doflist,(const double*)Ke_gg,ADD_VALUES);
     3009
     3010        cleanup_and_return:
     3011        xfree((void**)&first_gauss_area_coord);
     3012        xfree((void**)&second_gauss_area_coord);
     3013        xfree((void**)&third_gauss_area_coord);
     3014        xfree((void**)&gauss_weights);
     3015        delete friction;
     3016
     3017}       
     3018/*}}}*/
     3019/*FUNCTION Tria::CreateKMatrixDiagnosticHutter{{{1*/
     3020void  Tria::CreateKMatrixDiagnosticHutter(Mat Kgg){
     3021
     3022        /*Collapsed formulation: */
     3023        Sing*  sing=NULL;
     3024        int    i;
     3025
     3026        /*flags: */
     3027        bool onwater;
     3028
     3029        /*recover some inputs: */
     3030        inputs->GetParameterValue(&onwater,ElementOnWaterEnum);
     3031
     3032        /*If on water, skip: */
     3033        if(onwater)return;
     3034
     3035        /*Spawn 3 sing elements: */
     3036        for(i=0;i<3;i++){
     3037                sing=(Sing*)SpawnSing(i);
     3038                sing->CreateKMatrix(Kgg);
     3039        }
     3040
     3041        /*clean up*/
     3042        delete sing;
     3043
     3044}
     3045/*}}}*/
     3046/*FUNCTION Tria::CreateKMatrixDiagnosticSurfaceVert {{{1*/
     3047void  Tria::CreateKMatrixDiagnosticSurfaceVert(Mat Kgg){
     3048
     3049        int i,j;
     3050
     3051        /* node data: */
     3052        const int    numgrids=3;
     3053        const int    NDOF1=1;
     3054        const int    numdof=NDOF1*numgrids;
     3055        double       xyz_list[numgrids][3];
     3056        int          doflist[numdof];
     3057        int          numberofdofspernode;
     3058
     3059        /* gaussian points: */
     3060        int     num_gauss,ig;
     3061        double* first_gauss_area_coord  =  NULL;
     3062        double* second_gauss_area_coord =  NULL;
     3063        double* third_gauss_area_coord  =  NULL;
     3064        double* gauss_weights           =  NULL;
     3065        double  gauss_weight;
     3066        double  gauss_l1l2l3[3];
     3067
     3068
     3069        /* surface normal: */
     3070        double x4,y4,z4;
     3071        double x5,y5,z5;
     3072        double x6,y6,z6;
     3073        double v46[3];
     3074        double v56[3];
     3075        double normal[3];
     3076        double norm_normal;
     3077        double nz;
     3078
     3079        /*Matrices: */
     3080        double DL_scalar;
     3081        double L[3];
     3082        double Jdet;
     3083
     3084        /* local element matrices: */
     3085        double Ke_gg[numdof][numdof]={0.0}; //local element stiffness matrix
     3086        double Ke_gg_gaussian[numdof][numdof]; //stiffness matrix evaluated at the gaussian point.
     3087
     3088        /* Get node coordinates and dof list: */
     3089        GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
     3090        GetDofList(&doflist[0],&numberofdofspernode);
     3091
     3092        /* Get gaussian points and weights (make this a statically initialized list of points? fstd): */
     3093        GaussTria( &num_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &gauss_weights, 2);
     3094
     3095        /*Build normal vector to the surface:*/
     3096
     3097        x4=xyz_list[0][0];
     3098        y4=xyz_list[0][1];
     3099        z4=xyz_list[0][2];
     3100
     3101        x5=xyz_list[1][0];
     3102        y5=xyz_list[1][1];
     3103        z5=xyz_list[1][2];
     3104
     3105        x6=xyz_list[2][0];
     3106        y6=xyz_list[2][1];
     3107        z6=xyz_list[2][2];
     3108
     3109        v46[0]=x4-x6;
     3110        v46[1]=y4-y6;
     3111        v46[2]=z4-z6;
     3112
     3113        v56[0]=x5-x6;
     3114        v56[1]=y5-y6;
     3115        v56[2]=z5-z6;
     3116
     3117        normal[0]=(y4-y6)*(z5-z6)-(z4-z6)*(y5-y6);
     3118        normal[1]=(z4-z6)*(x5-x6)-(x4-x6)*(z5-z6);
     3119        normal[2]=(x4-x6)*(y5-y6)-(y4-y6)*(x5-x6);
     3120
     3121        norm_normal=sqrt(pow(normal[0],(double)2)+pow(normal[1],(double)2)+pow(normal[2],(double)2));
     3122        nz=1.0/norm_normal*normal[2];
     3123
     3124        /* Start  looping on the number of gaussian points: */
     3125        for (ig=0; ig<num_gauss; ig++){
     3126                /*Pick up the gaussian point: */
     3127                gauss_weight=*(gauss_weights+ig);
     3128                gauss_l1l2l3[0]=*(first_gauss_area_coord+ig);
     3129                gauss_l1l2l3[1]=*(second_gauss_area_coord+ig);
     3130                gauss_l1l2l3[2]=*(third_gauss_area_coord+ig);
     3131
     3132                /* Get Jacobian determinant: */
     3133                GetJacobianDeterminant3d(&Jdet, &xyz_list[0][0],gauss_l1l2l3);
     3134
     3135                //Get L matrix if viscous basal drag present:
     3136                GetL(&L[0], &xyz_list[0][0], gauss_l1l2l3,NDOF1);
     3137
     3138                /**********************Do not forget the sign**********************************/
     3139                DL_scalar=- gauss_weight*Jdet*nz;
     3140                /******************************************************************************/
     3141
     3142                /*  Do the triple producte tL*D*L: */
     3143                TripleMultiply( L,1,3,1,
     3144                                        &DL_scalar,1,1,0,
     3145                                        L,1,3,0,
     3146                                        &Ke_gg_gaussian[0][0],0);
     3147
     3148                /* Add the Ke_gg_gaussian, onto Ke_gg: */
     3149                for( i=0; i<numdof; i++) for(j=0;j<numdof;j++) Ke_gg[i][j]+=Ke_gg_gaussian[i][j];
     3150
     3151
     3152        } //for (ig=0; ig<num_gauss; ig++)
     3153
     3154        /*Add Ke_gg to global matrix Kgg: */
     3155        MatSetValues(Kgg,numdof,doflist,numdof,doflist,(const double*)Ke_gg,ADD_VALUES);
     3156
     3157cleanup_and_return:
     3158        xfree((void**)&first_gauss_area_coord);
     3159        xfree((void**)&second_gauss_area_coord);
     3160        xfree((void**)&third_gauss_area_coord);
     3161        xfree((void**)&gauss_weights);
     3162}
     3163/*}}}*/
     3164/*FUNCTION Tria::CreateKMatrixMelting {{{1*/
     3165void  Tria::CreateKMatrixMelting(Mat Kgg){
     3166
     3167        /*indexing: */
     3168        int i,j;
     3169
     3170        const int  numgrids=3;
     3171        const int  NDOF1=1;
     3172        const int  numdof=numgrids*NDOF1;
     3173        int        doflist[numdof];
     3174        int        numberofdofspernode;
     3175
     3176        /*Grid data: */
     3177        double     xyz_list[numgrids][3];
     3178
     3179        /*Material constants */
     3180        double     heatcapacity,latentheat;
     3181
     3182        /* gaussian points: */
     3183        int     num_area_gauss,ig;
     3184        double* gauss_weights  =  NULL;
     3185        double* first_gauss_area_coord  =  NULL;
     3186        double* second_gauss_area_coord =  NULL;
     3187        double* third_gauss_area_coord  =  NULL;
     3188        double  gauss_weight;
     3189        double  gauss_coord[3];
     3190
     3191        /*matrices: */
     3192        double     Jdet;
     3193        double     D_scalar;
     3194        double     K_terms[numdof][numdof]={0.0};
     3195        double     L[3];
     3196        double     tLD[3];
     3197        double     Ke_gaussian[numdof][numdof]={0.0};
     3198
     3199        /*Recover constants of ice */
     3200        latentheat=matpar->GetLatentHeat();
     3201        heatcapacity=matpar->GetHeatCapacity();
     3202
     3203        /* Get node coordinates and dof list: */
     3204        GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
     3205        GetDofList(&doflist[0],&numberofdofspernode);
     3206
     3207        /* Get gaussian points and weights: */
     3208        GaussTria (&num_area_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &gauss_weights, 2);
     3209
     3210        /* Start looping on the number of gauss  (nodes on the bedrock) */
     3211        for (ig=0; ig<num_area_gauss; ig++){
     3212                gauss_weight=*(gauss_weights+ig);
     3213                gauss_coord[0]=*(first_gauss_area_coord+ig);
     3214                gauss_coord[1]=*(second_gauss_area_coord+ig);
     3215                gauss_coord[2]=*(third_gauss_area_coord+ig);
     3216
     3217                //Get the Jacobian determinant
     3218                GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0], gauss_coord);
     3219
     3220                /*Get L matrix : */
     3221                GetL(&L[0], &xyz_list[0][0], gauss_coord,NDOF1);
     3222
     3223                /*Calculate DL on gauss point */
     3224                D_scalar=latentheat/heatcapacity*gauss_weight*Jdet;
     3225
     3226                /*  Do the triple product tL*D*L: */
     3227                MatrixMultiply(&L[0],numdof,1,0,&D_scalar,1,1,0,&tLD[0],0);
     3228                MatrixMultiply(&tLD[0],numdof,1,0,&L[0],1,numdof,0,&Ke_gaussian[0][0],0);
     3229
     3230                for(i=0;i<numgrids;i++){
     3231                        for(j=0;j<numgrids;j++){
     3232                                K_terms[i][j]+=Ke_gaussian[i][j];
     3233                        }
     3234                }
     3235        }
     3236
     3237        /*Add Ke_gg to global matrix Kgg: */
     3238        MatSetValues(Kgg,numdof,doflist,numdof,doflist,(const double*)K_terms,ADD_VALUES);
     3239
     3240cleanup_and_return:
     3241        xfree((void**)&first_gauss_area_coord);
     3242        xfree((void**)&second_gauss_area_coord);
     3243        xfree((void**)&third_gauss_area_coord);
     3244        xfree((void**)&gauss_weights);
     3245
     3246}
     3247/*}}}*/
     3248/*FUNCTION Tria::CreateKMatrixPrognostic {{{1*/
     3249void  Tria::CreateKMatrixPrognostic(Mat Kgg){
     3250
     3251        /* local declarations */
     3252        int             i,j;
     3253
     3254        /* node data: */
     3255        const int    numgrids=3;
     3256        const int    NDOF1=1;
     3257        const int    numdof=NDOF1*numgrids;
     3258        double       xyz_list[numgrids][3];
     3259        int          doflist[numdof];
     3260        int          numberofdofspernode;
     3261
     3262        /* gaussian points: */
     3263        int     num_gauss,ig;
     3264        double* first_gauss_area_coord  =  NULL;
     3265        double* second_gauss_area_coord =  NULL;
     3266        double* third_gauss_area_coord  =  NULL;
     3267        double* gauss_weights           =  NULL;
     3268        double  gauss_weight;
     3269        double  gauss_l1l2l3[3];
     3270
     3271        /* matrices: */
     3272        double L[numgrids];
     3273        double B[2][numgrids];
     3274        double Bprime[2][numgrids];
     3275        double DL[2][2]={0.0};
     3276        double DLprime[2][2]={0.0};
     3277        double DL_scalar;
     3278        double Ke_gg[numdof][numdof]={0.0};
     3279        double Ke_gg_gaussian[numdof][numdof]={0.0};
     3280        double Ke_gg_thickness1[numdof][numdof]={0.0};
     3281        double Ke_gg_thickness2[numdof][numdof]={0.0};
     3282        double Jdettria;
     3283
     3284        /*input parameters for structural analysis (diagnostic): */
     3285        double  dvx[2];
     3286        double  dvy[2];
     3287        double  vx,vy;
     3288        double  dvxdx,dvydy;
     3289        double  v_gauss[2]={0.0};
     3290        double  K[2][2]={0.0};
     3291        double  KDL[2][2]={0.0};
     3292        int     dofs[2]={0,1};
     3293        int     found;
     3294
     3295        /*parameters: */
     3296        double dt;
     3297        bool artdiff;
     3298
     3299        /*retrieve some parameters: */
     3300        this->parameters->FindParam(&dt,DtEnum);
     3301        this->parameters->FindParam(&artdiff,ArtDiffEnum);
     3302
     3303        /* Get node coordinates and dof list: */
     3304        GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
     3305        GetDofList(&doflist[0],&numberofdofspernode);
     3306
     3307        //Create Artificial diffusivity once for all if requested
     3308        if(artdiff){
     3309                //Get the Jacobian determinant
     3310                gauss_l1l2l3[0]=ONETHIRD; gauss_l1l2l3[1]=ONETHIRD; gauss_l1l2l3[2]=ONETHIRD;
     3311                GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss_l1l2l3);
     3312
     3313                //Build K matrix (artificial diffusivity matrix)
     3314                inputs->GetParameterAverage(&v_gauss[0],VxAverageEnum);
     3315                inputs->GetParameterAverage(&v_gauss[1],VyAverageEnum);
     3316
     3317                K[0][0]=pow(Jdettria,(double).5)/2.0*fabs(v_gauss[0]);
     3318                K[1][1]=pow(Jdettria,(double).5)/2.0*fabs(v_gauss[1]);
     3319        }
     3320
     3321        /* Get gaussian points and weights (make this a statically initialized list of points? fstd): */
     3322        GaussTria( &num_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &gauss_weights, 2);
     3323
     3324        /* Start  looping on the number of gaussian points: */
     3325        for (ig=0; ig<num_gauss; ig++){
     3326
     3327                /*Pick up the gaussian point: */
     3328                gauss_weight=*(gauss_weights+ig);
     3329                gauss_l1l2l3[0]=*(first_gauss_area_coord+ig);
     3330                gauss_l1l2l3[1]=*(second_gauss_area_coord+ig);
     3331                gauss_l1l2l3[2]=*(third_gauss_area_coord+ig);
     3332
     3333                /* Get Jacobian determinant: */
     3334                GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss_l1l2l3);
     3335
     3336                /*Get L matrix: */
     3337                GetL(&L[0], &xyz_list[0][0], gauss_l1l2l3,numberofdofspernode);
     3338
     3339                DL_scalar=gauss_weight*Jdettria;
     3340
     3341                /*  Do the triple product tL*D*L: */
     3342                TripleMultiply( &L[0],1,numdof,1,
     3343                                        &DL_scalar,1,1,0,
     3344                                        &L[0],1,numdof,0,
     3345                                        &Ke_gg_gaussian[0][0],0);
     3346
     3347                /*Get B  and B prime matrix: */
     3348                GetB_prog(&B[0][0], &xyz_list[0][0], gauss_l1l2l3);
     3349                GetBPrime_prog(&Bprime[0][0], &xyz_list[0][0], gauss_l1l2l3);
     3350
     3351                //Get vx, vy and their derivatives at gauss point
     3352                inputs->GetParameterValue(&vx,&gauss_l1l2l3[0],VxAverageEnum);
     3353                inputs->GetParameterValue(&vy,&gauss_l1l2l3[0],VyAverageEnum);
     3354
     3355                inputs->GetParameterDerivativeValue(&dvx[0],&xyz_list[0][0],&gauss_l1l2l3[0],VxAverageEnum);
     3356                inputs->GetParameterDerivativeValue(&dvy[0],&xyz_list[0][0],&gauss_l1l2l3[0],VyAverageEnum);
     3357
     3358                dvxdx=dvx[0];
     3359                dvydy=dvy[1];
     3360
     3361                DL_scalar=dt*gauss_weight*Jdettria;
     3362
     3363                //Create DL and DLprime matrix
     3364                DL[0][0]=DL_scalar*dvxdx;
     3365                DL[1][1]=DL_scalar*dvydy;
     3366
     3367                DLprime[0][0]=DL_scalar*vx;
     3368                DLprime[1][1]=DL_scalar*vy;
     3369
     3370                //Do the triple product tL*D*L.
     3371                //Ke_gg_thickness=B'*DL*B+B'*DLprime*Bprime;
     3372
     3373                TripleMultiply( &B[0][0],2,numdof,1,
     3374                                        &DL[0][0],2,2,0,
     3375                                        &B[0][0],2,numdof,0,
     3376                                        &Ke_gg_thickness1[0][0],0);
     3377
     3378                TripleMultiply( &B[0][0],2,numdof,1,
     3379                                        &DLprime[0][0],2,2,0,
     3380                                        &Bprime[0][0],2,numdof,0,
     3381                                        &Ke_gg_thickness2[0][0],0);
     3382
     3383                /* Add the Ke_gg_gaussian, and optionally Ke_gg_drag_gaussian onto Ke_gg: */
     3384                for( i=0; i<numdof; i++) for(j=0;j<numdof;j++) Ke_gg[i][j]+=Ke_gg_gaussian[i][j];
     3385                for( i=0; i<numdof; i++) for(j=0;j<numdof;j++) Ke_gg[i][j]+=Ke_gg_thickness1[i][j];
     3386                for( i=0; i<numdof; i++) for(j=0;j<numdof;j++) Ke_gg[i][j]+=Ke_gg_thickness2[i][j];
     3387
     3388                if(artdiff){
     3389
     3390                        /* Compute artificial diffusivity */
     3391                        KDL[0][0]=DL_scalar*K[0][0];
     3392                        KDL[1][1]=DL_scalar*K[1][1];
     3393
     3394                        TripleMultiply( &Bprime[0][0],2,numdof,1,
     3395                                                &KDL[0][0],2,2,0,
     3396                                                &Bprime[0][0],2,numdof,0,
     3397                                                &Ke_gg_gaussian[0][0],0);
     3398
     3399                        /* Add artificial diffusivity matrix */
     3400                        for( i=0; i<numdof; i++) for(j=0;j<numdof;j++) Ke_gg[i][j]+=Ke_gg_gaussian[i][j];
     3401
     3402                }
     3403
     3404        } // for (ig=0; ig<num_gauss; ig++)
     3405
     3406        /*Add Ke_gg to global matrix Kgg: */
     3407        MatSetValues(Kgg,numdof,doflist,numdof,doflist,(const double*)Ke_gg,ADD_VALUES);
     3408
     3409
     3410cleanup_and_return:
     3411        xfree((void**)&first_gauss_area_coord);
     3412        xfree((void**)&second_gauss_area_coord);
     3413        xfree((void**)&third_gauss_area_coord);
     3414        xfree((void**)&gauss_weights);
     3415
     3416}
     3417/*}}}*/
     3418/*FUNCTION Tria::CreateKMatrixPrognostic2 {{{1*/
     3419void  Tria::CreateKMatrixPrognostic2(Mat Kgg){
     3420
     3421        /* local declarations */
     3422        int             i,j;
     3423
     3424        /* node data: */
     3425        const int    numgrids=3;
     3426        const int    NDOF1=1;
     3427        const int    numdof=NDOF1*numgrids;
     3428        double       xyz_list[numgrids][3];
     3429        int          doflist[numdof];
     3430        int          numberofdofspernode;
     3431
     3432        /* gaussian points: */
     3433        int     num_gauss,ig;
     3434        double* first_gauss_area_coord  =  NULL;
     3435        double* second_gauss_area_coord =  NULL;
     3436        double* third_gauss_area_coord  =  NULL;
     3437        double* gauss_weights           =  NULL;
     3438        double  gauss_weight;
     3439        double  gauss_l1l2l3[3];
     3440
     3441        /* matrices: */
     3442        double L[numgrids];
     3443        double B[2][numgrids];
     3444        double Bprime[2][numgrids];
     3445        double DL[2][2]={0.0};
     3446        double DLprime[2][2]={0.0};
     3447        double DL_scalar;
     3448        double Ke_gg[numdof][numdof]={0.0};
     3449        double Ke_gg1[numdof][numdof]={0.0};
     3450        double Ke_gg2[numdof][numdof]={0.0};
     3451        double Jdettria;
     3452
     3453        /*input parameters for structural analysis (diagnostic): */
     3454        double  vx,vy;
     3455        int     dofs[1]={0};
     3456        int     found;
     3457
     3458        /*parameters: */
     3459        double dt;
     3460
     3461        /*retrieve some parameters: */
     3462        this->parameters->FindParam(&dt,DtEnum);
     3463
     3464        /* Get node coordinates and dof list: */
     3465        GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
     3466        GetDofList(&doflist[0],&numberofdofspernode);
     3467
     3468        /* Get gaussian points and weights (make this a statically initialized list of points? fstd): */
     3469        GaussTria( &num_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &gauss_weights, 2);
     3470
     3471        /* Start  looping on the number of gaussian points: */
     3472        for (ig=0; ig<num_gauss; ig++){
     3473
     3474                /*Pick up the gaussian point: */
     3475                gauss_weight=*(gauss_weights+ig);
     3476                gauss_l1l2l3[0]=*(first_gauss_area_coord+ig);
     3477                gauss_l1l2l3[1]=*(second_gauss_area_coord+ig);
     3478                gauss_l1l2l3[2]=*(third_gauss_area_coord+ig);
     3479
     3480                /* Get Jacobian determinant: */
     3481                GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss_l1l2l3);
     3482
     3483                /*Get L matrix: */
     3484                GetL(&L[0], &xyz_list[0][0], gauss_l1l2l3,numberofdofspernode);
     3485
     3486                DL_scalar=gauss_weight*Jdettria;
     3487
     3488                /*  Do the triple product tL*D*L: */
     3489                TripleMultiply( &L[0],1,numdof,1,
     3490                                        &DL_scalar,1,1,0,
     3491                                        &L[0],1,numdof,0,
     3492                                        &Ke_gg1[0][0],0);
     3493
     3494                /*Get B  and B prime matrix: */
     3495                /*WARNING: B and Bprime are inverted compared to usual prognostic!!!!*/
     3496                GetB_prog(&Bprime[0][0], &xyz_list[0][0], gauss_l1l2l3);
     3497                GetBPrime_prog(&B[0][0], &xyz_list[0][0], gauss_l1l2l3);
     3498
     3499                //Get vx, vy and their derivatives at gauss point
     3500                inputs->GetParameterValue(&vx,&gauss_l1l2l3[0],VxAverageEnum);
     3501                inputs->GetParameterValue(&vy,&gauss_l1l2l3[0],VyAverageEnum);
     3502
     3503                DL_scalar=-dt*gauss_weight*Jdettria;
     3504
     3505                DLprime[0][0]=DL_scalar*vx;
     3506                DLprime[1][1]=DL_scalar*vy;
     3507
     3508                //Do the triple product tL*D*L.
     3509                TripleMultiply( &B[0][0],2,numdof,1,
     3510                                        &DLprime[0][0],2,2,0,
     3511                                        &Bprime[0][0],2,numdof,0,
     3512                                        &Ke_gg2[0][0],0);
     3513
     3514                /* Add the Ke_gg_gaussian, and optionally Ke_gg_drag_gaussian onto Ke_gg: */
     3515                for( i=0; i<numdof; i++) for(j=0;j<numdof;j++) Ke_gg[i][j]+=Ke_gg1[i][j];
     3516                for( i=0; i<numdof; i++) for(j=0;j<numdof;j++) Ke_gg[i][j]+=Ke_gg2[i][j];
     3517
     3518        } // for (ig=0; ig<num_gauss; ig++)
     3519
     3520        /*Add Ke_gg to global matrix Kgg: */
     3521        MatSetValues(Kgg,numdof,doflist,numdof,doflist,(const double*)Ke_gg,ADD_VALUES);
     3522
     3523
     3524cleanup_and_return:
     3525        xfree((void**)&first_gauss_area_coord);
     3526        xfree((void**)&second_gauss_area_coord);
     3527        xfree((void**)&third_gauss_area_coord);
     3528        xfree((void**)&gauss_weights);
     3529
     3530}
     3531/*}}}*/
     3532/*FUNCTION Tria::CreateKMatrixSlopeCompute {{{1*/
     3533
     3534void  Tria::CreateKMatrixSlopeCompute(Mat Kgg){
     3535
     3536        /* local declarations */
     3537        int             i,j;
     3538
     3539        /* node data: */
     3540        const int    numgrids=3;
     3541        const int    NDOF1=1;
     3542        const int    numdof=NDOF1*numgrids;
     3543        double       xyz_list[numgrids][3];
     3544        int          doflist[numdof];
     3545        int          numberofdofspernode;
     3546       
     3547        /* gaussian points: */
     3548        int     num_gauss,ig;
     3549        double* first_gauss_area_coord  =  NULL;
     3550        double* second_gauss_area_coord =  NULL;
     3551        double* third_gauss_area_coord  =  NULL;
     3552        double* gauss_weights           =  NULL;
     3553        double  gauss_weight;
     3554        double  gauss_l1l2l3[3];
     3555
     3556        /* matrices: */
     3557        double L[1][3];
     3558        double DL_scalar;
     3559
     3560        /* local element matrices: */
     3561        double Ke_gg[numdof][numdof]={0.0}; //local element stiffness matrix
     3562        double Ke_gg_gaussian[numdof][numdof]; //stiffness matrix evaluated at the gaussian point.
     3563       
     3564        double Jdet;
     3565
     3566        /* Get node coordinates and dof list: */
     3567        GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
     3568        GetDofList(&doflist[0],&numberofdofspernode);
     3569
     3570        /* Get gaussian points and weights (make this a statically initialized list of points? fstd): */
     3571        GaussTria( &num_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &gauss_weights, 2);
     3572
     3573        /* Start  looping on the number of gaussian points: */
     3574        for (ig=0; ig<num_gauss; ig++){
     3575                /*Pick up the gaussian point: */
     3576                gauss_weight=*(gauss_weights+ig);
     3577                gauss_l1l2l3[0]=*(first_gauss_area_coord+ig);
     3578                gauss_l1l2l3[1]=*(second_gauss_area_coord+ig);
     3579                gauss_l1l2l3[2]=*(third_gauss_area_coord+ig);
     3580
     3581               
     3582                /*Get L matrix: */
     3583                GetL(&L[0][0], &xyz_list[0][0], gauss_l1l2l3,NDOF1);
     3584
     3585                /* Get Jacobian determinant: */
     3586                GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0],gauss_l1l2l3);
     3587               
     3588                DL_scalar=gauss_weight*Jdet;
     3589
     3590                /*  Do the triple producte tL*D*L: */
     3591                TripleMultiply( &L[0][0],1,3,1,
     3592                                        &DL_scalar,1,1,0,
     3593                                        &L[0][0],1,3,0,
     3594                                        &Ke_gg_gaussian[0][0],0);
     3595
     3596                /* Add the Ke_gg_gaussian, and optionally Ke_gg_drag_gaussian onto Ke_gg: */
     3597                for( i=0; i<numdof; i++) for(j=0;j<numdof;j++) Ke_gg[i][j]+=Ke_gg_gaussian[i][j];
     3598        } //for (ig=0; ig<num_gauss; ig++
     3599
     3600        /*Add Ke_gg to global matrix Kgg: */
     3601        MatSetValues(Kgg,numdof,doflist,numdof,doflist,(const double*)Ke_gg,ADD_VALUES);
     3602               
     3603        cleanup_and_return:
     3604        xfree((void**)&first_gauss_area_coord);
     3605        xfree((void**)&second_gauss_area_coord);
     3606        xfree((void**)&third_gauss_area_coord);
     3607        xfree((void**)&gauss_weights);
     3608}
     3609/*}}}*/
     3610/*FUNCTION Tria::CreateKMatrixThermal {{{1*/
     3611void  Tria::CreateKMatrixThermal(Mat Kgg){
     3612
     3613        int i,j;
     3614        int found=0;
     3615       
     3616        /* node data: */
     3617        const int    numgrids=3;
     3618        const int    NDOF1=1;
     3619        const int    numdof=NDOF1*numgrids;
     3620        double       xyz_list[numgrids][3];
     3621        int          doflist[numdof];
     3622        int          numberofdofspernode;
     3623
     3624        double mixed_layer_capacity;
     3625        double thermal_exchange_velocity;
     3626        double rho_water;
     3627        double rho_ice;
     3628        double heatcapacity;
     3629
     3630        int     num_gauss,ig;
     3631        double* first_gauss_area_coord  =  NULL;
     3632        double* second_gauss_area_coord =  NULL;
     3633        double* third_gauss_area_coord  =  NULL;
     3634        double* gauss_weights           =  NULL;
     3635        double  gauss_weight;
     3636        double  gauss_coord[3];
     3637
     3638        /*matrices: */
     3639        double  Jdet;
     3640        double  K_terms[numdof][numdof]={0.0};
     3641        double  Ke_gaussian[numdof][numdof]={0.0};
     3642        double  l1l2l3[numgrids];
     3643        double     tl1l2l3D[3];
     3644        double  D_scalar;
     3645
     3646        /*parameters: */
     3647        double dt;
     3648
     3649        /*retrieve some parameters: */
     3650        this->parameters->FindParam(&dt,DtEnum);
     3651
     3652        /* Get node coordinates and dof list: */
     3653        GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
     3654        GetDofList(&doflist[0],&numberofdofspernode);
     3655
     3656        //recover material parameters
     3657        mixed_layer_capacity=matpar->GetMixedLayerCapacity();
     3658        thermal_exchange_velocity=matpar->GetThermalExchangeVelocity();
     3659        rho_water=matpar->GetRhoWater();
     3660        rho_ice=matpar->GetRhoIce();
     3661        heatcapacity=matpar->GetHeatCapacity();
     3662
     3663
     3664        GaussTria (&num_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &gauss_weights, 2);
     3665
     3666        /* Start looping on the number of gauss (nodes on the bedrock) */
     3667        for (ig=0; ig<num_gauss; ig++){
     3668                gauss_weight=*(gauss_weights+ig);
     3669                gauss_coord[0]=*(first_gauss_area_coord+ig);
     3670                gauss_coord[1]=*(second_gauss_area_coord+ig);
     3671                gauss_coord[2]=*(third_gauss_area_coord+ig);
     3672               
     3673                //Get the Jacobian determinant
     3674                GetJacobianDeterminant3d(&Jdet, &xyz_list[0][0], gauss_coord);
     3675               
     3676                /*Get nodal functions values: */
     3677                GetNodalFunctions(&l1l2l3[0], gauss_coord);
     3678                               
     3679                /*Calculate DL on gauss point */
     3680                D_scalar=gauss_weight*Jdet*rho_water*mixed_layer_capacity*thermal_exchange_velocity/(heatcapacity*rho_ice);
     3681                if(dt){
     3682                        D_scalar=dt*D_scalar;
     3683                }
     3684
     3685                /*  Do the triple product tL*D*L: */
     3686                MatrixMultiply(&l1l2l3[0],numdof,1,0,&D_scalar,1,1,0,&tl1l2l3D[0],0);
     3687                MatrixMultiply(&tl1l2l3D[0],numdof,1,0,&l1l2l3[0],1,numdof,0,&Ke_gaussian[0][0],0);
     3688
     3689                for(i=0;i<3;i++){
     3690                        for(j=0;j<3;j++){
     3691                                K_terms[i][j]+=Ke_gaussian[i][j];
     3692                        }
     3693                }
     3694        }
     3695       
     3696        /*Add Ke_gg to global matrix Kgg: */
     3697        MatSetValues(Kgg,numdof,doflist,numdof,doflist,(const double*)K_terms,ADD_VALUES);
     3698
     3699        cleanup_and_return:
     3700        xfree((void**)&first_gauss_area_coord);
     3701        xfree((void**)&second_gauss_area_coord);
     3702        xfree((void**)&third_gauss_area_coord);
     3703        xfree((void**)&gauss_weights);
     3704
     3705}
     3706/*}}}*/
     3707/*FUNCTION Tria::CreatePVectorBalancedthickness {{{1*/
     3708void  Tria::CreatePVectorBalancedthickness(Vec pg ){
     3709
     3710
     3711        /* local declarations */
     3712        int             i,j;
     3713
     3714        /* node data: */
     3715        const int    numgrids=3;
     3716        const int    NDOF1=1;
     3717        const int    numdof=NDOF1*numgrids;
     3718        double       xyz_list[numgrids][3];
     3719        int          doflist[numdof];
     3720        int          numberofdofspernode;
     3721
     3722        /* gaussian points: */
     3723        int     num_gauss,ig;
     3724        double* first_gauss_area_coord  =  NULL;
     3725        double* second_gauss_area_coord =  NULL;
     3726        double* third_gauss_area_coord  =  NULL;
     3727        double* gauss_weights           =  NULL;
     3728        double  gauss_weight;
     3729        double  gauss_l1l2l3[3];
     3730
     3731        /* matrix */
     3732        double pe_g[numgrids]={0.0};
     3733        double L[numgrids];
     3734        double Jdettria;
     3735
     3736        /*input parameters for structural analysis (diagnostic): */
     3737        double  accumulation_g;
     3738        double  melting_g;
     3739
     3740        /* Get node coordinates and dof list: */
     3741        GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
     3742        GetDofList(&doflist[0],&numberofdofspernode);
     3743
     3744        /* Get gaussian points and weights (make this a statically initialized list of points? fstd): */
     3745        GaussTria( &num_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &gauss_weights, 2);
     3746
     3747        /* Start  looping on the number of gaussian points: */
     3748        for (ig=0; ig<num_gauss; ig++){
     3749                /*Pick up the gaussian point: */
     3750                gauss_weight=*(gauss_weights+ig);
     3751                gauss_l1l2l3[0]=*(first_gauss_area_coord+ig);
     3752                gauss_l1l2l3[1]=*(second_gauss_area_coord+ig);
     3753                gauss_l1l2l3[2]=*(third_gauss_area_coord+ig);
     3754
     3755                /* Get Jacobian determinant: */
     3756                GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss_l1l2l3);
     3757
     3758                /*Get L matrix: */
     3759                GetL(&L[0], &xyz_list[0][0], gauss_l1l2l3,numberofdofspernode);
     3760
     3761                /* Get accumulation, melting at gauss point */
     3762                inputs->GetParameterValue(&accumulation_g, &gauss_l1l2l3[0],AccumulationRateEnum);
     3763                inputs->GetParameterValue(&melting_g, &gauss_l1l2l3[0],MeltingRateEnum);
     3764
     3765                /* Add value into pe_g: */
     3766                for( i=0; i<numdof; i++) pe_g[i]+=Jdettria*gauss_weight*(accumulation_g-melting_g)*L[i];
     3767
     3768        } // for (ig=0; ig<num_gauss; ig++)
     3769
     3770        /*Add pe_g to global matrix Kgg: */
     3771        VecSetValues(pg,numdof,doflist,(const double*)pe_g,ADD_VALUES);
     3772
     3773cleanup_and_return:
     3774        xfree((void**)&first_gauss_area_coord);
     3775        xfree((void**)&second_gauss_area_coord);
     3776        xfree((void**)&third_gauss_area_coord);
     3777        xfree((void**)&gauss_weights);
     3778
     3779}
     3780/*}}}*/
     3781/*FUNCTION Tria::CreatePVectorBalancedthickness2 {{{1*/
     3782void  Tria::CreatePVectorBalancedthickness2(Vec pg){
     3783
     3784
     3785        /* local declarations */
     3786        int             i,j;
     3787
     3788        /* node data: */
     3789        const int    numgrids=3;
     3790        const int    NDOF1=1;
     3791        const int    numdof=NDOF1*numgrids;
     3792        double       xyz_list[numgrids][3];
     3793        int          doflist[numdof];
     3794        int          numberofdofspernode;
     3795
     3796        /* gaussian points: */
     3797        int     num_gauss,ig;
     3798        double* first_gauss_area_coord  =  NULL;
     3799        double* second_gauss_area_coord =  NULL;
     3800        double* third_gauss_area_coord  =  NULL;
     3801        double* gauss_weights           =  NULL;
     3802        double  gauss_weight;
     3803        double  gauss_l1l2l3[3];
     3804
     3805        /* matrix */
     3806        double pe_g[numgrids]={0.0};
     3807        double L[numgrids];
     3808        double Jdettria;
     3809
     3810        /*input parameters for structural analysis (diagnostic): */
     3811        double  accumulation_g;
     3812        double  melting_g;
     3813        double  dhdt_g;
     3814
     3815        /* Get node coordinates and dof list: */
     3816        GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
     3817        GetDofList(&doflist[0],&numberofdofspernode);
     3818
     3819        /* Get gaussian points and weights (make this a statically initialized list of points? fstd): */
     3820        GaussTria( &num_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &gauss_weights, 2);
     3821
     3822        /* Start  looping on the number of gaussian points: */
     3823        for (ig=0; ig<num_gauss; ig++){
     3824                /*Pick up the gaussian point: */
     3825                gauss_weight=*(gauss_weights+ig);
     3826                gauss_l1l2l3[0]=*(first_gauss_area_coord+ig);
     3827                gauss_l1l2l3[1]=*(second_gauss_area_coord+ig);
     3828                gauss_l1l2l3[2]=*(third_gauss_area_coord+ig);
     3829
     3830                /* Get Jacobian determinant: */
     3831                GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss_l1l2l3);
     3832
     3833                /*Get L matrix: */
     3834                GetL(&L[0], &xyz_list[0][0], gauss_l1l2l3,numberofdofspernode);
     3835
     3836                /* Get accumulation, melting and thickness at gauss point */
     3837                inputs->GetParameterValue(&accumulation_g, &gauss_l1l2l3[0],AccumulationRateEnum);
     3838                inputs->GetParameterValue(&melting_g, &gauss_l1l2l3[0],MeltingRateEnum);
     3839                inputs->GetParameterValue(&dhdt_g, &gauss_l1l2l3[0],DhDtEnum);
     3840
     3841                /* Add value into pe_g: */
     3842                for( i=0; i<numdof; i++) pe_g[i]+=Jdettria*gauss_weight*(accumulation_g-melting_g+dhdt_g)*L[i];
     3843
     3844        } // for (ig=0; ig<num_gauss; ig++)
     3845
     3846        /*Add pe_g to global matrix Kgg: */
     3847        VecSetValues(pg,numdof,doflist,(const double*)pe_g,ADD_VALUES);
     3848
     3849cleanup_and_return:
     3850        xfree((void**)&first_gauss_area_coord);
     3851        xfree((void**)&second_gauss_area_coord);
     3852        xfree((void**)&third_gauss_area_coord);
     3853        xfree((void**)&gauss_weights);
     3854
     3855}
     3856/*}}}*/
     3857/*FUNCTION Tria::CreatePVectorBalancedvelocities {{{1*/
     3858void  Tria::CreatePVectorBalancedvelocities(Vec pg){
     3859
     3860
     3861        /* local declarations */
     3862        int             i,j;
     3863
     3864        /* node data: */
     3865        const int    numgrids=3;
     3866        const int    NDOF1=1;
     3867        const int    numdof=NDOF1*numgrids;
     3868        double       xyz_list[numgrids][3];
     3869        int          doflist[numdof];
     3870        int          numberofdofspernode;
     3871
     3872        /* gaussian points: */
     3873        int     num_gauss,ig;
     3874        double* first_gauss_area_coord  =  NULL;
     3875        double* second_gauss_area_coord =  NULL;
     3876        double* third_gauss_area_coord  =  NULL;
     3877        double* gauss_weights           =  NULL;
     3878        double  gauss_weight;
     3879        double  gauss_l1l2l3[3];
     3880
     3881        /* matrix */
     3882        double pe_g[numgrids]={0.0};
     3883        double L[numgrids];
     3884        double Jdettria;
     3885
     3886        /*input parameters for structural analysis (diagnostic): */
     3887        double  accumulation_g;
     3888        double  melting_g;
     3889
     3890        /* Get node coordinates and dof list: */
     3891        GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
     3892        GetDofList(&doflist[0],&numberofdofspernode);
     3893
     3894        /* Get gaussian points and weights (make this a statically initialized list of points? fstd): */
     3895        GaussTria( &num_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &gauss_weights, 2);
     3896
     3897        /* Start  looping on the number of gaussian points: */
     3898        for (ig=0; ig<num_gauss; ig++){
     3899                /*Pick up the gaussian point: */
     3900                gauss_weight=*(gauss_weights+ig);
     3901                gauss_l1l2l3[0]=*(first_gauss_area_coord+ig);
     3902                gauss_l1l2l3[1]=*(second_gauss_area_coord+ig);
     3903                gauss_l1l2l3[2]=*(third_gauss_area_coord+ig);
     3904
     3905                /* Get Jacobian determinant: */
     3906                GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss_l1l2l3);
     3907
     3908                /*Get L matrix: */
     3909                GetL(&L[0], &xyz_list[0][0], gauss_l1l2l3,numberofdofspernode);
     3910
     3911                /* Get accumulation, melting at gauss point */
     3912                inputs->GetParameterValue(&accumulation_g, &gauss_l1l2l3[0],AccumulationRateEnum);
     3913                inputs->GetParameterValue(&melting_g, &gauss_l1l2l3[0],MeltingRateEnum);
     3914
     3915                /* Add value into pe_g: */
     3916                for( i=0; i<numdof; i++) pe_g[i]+=Jdettria*gauss_weight*(accumulation_g-melting_g)*L[i];
     3917
     3918        } // for (ig=0; ig<num_gauss; ig++)
     3919
     3920        /*Add pe_g to global matrix Kgg: */
     3921        VecSetValues(pg,numdof,doflist,(const double*)pe_g,ADD_VALUES);
     3922
     3923cleanup_and_return:
     3924        xfree((void**)&first_gauss_area_coord);
     3925        xfree((void**)&second_gauss_area_coord);
     3926        xfree((void**)&third_gauss_area_coord);
     3927        xfree((void**)&gauss_weights);
     3928
     3929}
     3930/*}}}*/
     3931/*FUNCTION Tria::CreatePVectorDiagnosticBaseVert {{{1*/
     3932void  Tria::CreatePVectorDiagnosticBaseVert(Vec pg){
     3933
     3934        int             i,j;
     3935
     3936        /* node data: */
     3937        const int    numgrids=3;
     3938        const int    NDOF1=1;
     3939        const int    numdof=NDOF1*numgrids;
     3940        double       xyz_list[numgrids][3];
     3941        int          doflist[numdof];
     3942        int          numberofdofspernode;
     3943
     3944        /* gaussian points: */
     3945        int     num_gauss,ig;
     3946        double* first_gauss_area_coord  =  NULL;
     3947        double* second_gauss_area_coord =  NULL;
     3948        double* third_gauss_area_coord  =  NULL;
     3949        double* gauss_weights           =  NULL;
     3950        double  gauss_weight;
     3951        double  gauss_l1l2l3[3];
     3952
     3953        /* Jacobian: */
     3954        double Jdet;
     3955
     3956        /*nodal functions: */
     3957        double l1l2l3[3];
     3958
     3959        /*element vector at the gaussian points: */
     3960        double  pe_g[numdof]={0.0};
     3961        double  pe_g_gaussian[numdof];
     3962
     3963        /* matrices: */
     3964        double L[numgrids];
     3965
     3966        /*input parameters for structural analysis (diagnostic): */
     3967        double  vx,vy;
     3968        double  meltingvalue;
     3969        double  slope[2];
     3970        double  dbdx,dbdy;
     3971
     3972        /* Get node coordinates and dof list: */
     3973        GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
     3974        GetDofList(&doflist[0],&numberofdofspernode);
     3975
     3976        /* Get gaussian points and weights (make this a statically initialized list of points? fstd): */
     3977        GaussTria( &num_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &gauss_weights, 2);
     3978
     3979        /*For icesheets: */
     3980        /* Start  looping on the number of gaussian points: */
     3981        for (ig=0; ig<num_gauss; ig++){
     3982
     3983                /*Pick up the gaussian point: */
     3984                gauss_weight=*(gauss_weights+ig);
     3985                gauss_l1l2l3[0]=*(first_gauss_area_coord+ig);
     3986                gauss_l1l2l3[1]=*(second_gauss_area_coord+ig);
     3987                gauss_l1l2l3[2]=*(third_gauss_area_coord+ig);
     3988
     3989                /*Get melting at gaussian point: */
     3990                inputs->GetParameterValue(&meltingvalue, &gauss_l1l2l3[0],MeltingRateEnum);
     3991
     3992                /*Get velocity at gaussian point: */
     3993                inputs->GetParameterValue(&vx, &gauss_l1l2l3[0],VxEnum);
     3994                inputs->GetParameterValue(&vy, &gauss_l1l2l3[0],VyEnum);
     3995
     3996                /*Get bed slope: */
     3997                inputs->GetParameterDerivativeValue(&slope[0],&xyz_list[0][0],&gauss_l1l2l3[0],BedEnum);
     3998                dbdx=slope[0];
     3999                dbdy=slope[1];
     4000
     4001                /* Get Jacobian determinant: */
     4002                GetJacobianDeterminant3d(&Jdet, &xyz_list[0][0],gauss_l1l2l3);
     4003
     4004                //Get L matrix if viscous basal drag present:
     4005                GetL(&L[0], &xyz_list[0][0], gauss_l1l2l3,NDOF1);
     4006
     4007
     4008                /*Build gaussian vector: */
     4009                for(i=0;i<numgrids;i++){
     4010                        pe_g_gaussian[i]=-Jdet*gauss_weight*(vx*dbdx+vy*dbdy-meltingvalue)*L[i];
     4011                }
     4012
     4013                /*Add pe_g_gaussian vector to pe_g: */
     4014                for( i=0; i<numdof; i++)pe_g[i]+=pe_g_gaussian[i];
     4015
     4016        }
     4017
     4018        /*Add pe_g to global vector pg: */
     4019        VecSetValues(pg,numdof,doflist,(const double*)pe_g,ADD_VALUES);
     4020
     4021cleanup_and_return:
     4022        xfree((void**)&first_gauss_area_coord);
     4023        xfree((void**)&second_gauss_area_coord);
     4024        xfree((void**)&third_gauss_area_coord);
     4025        xfree((void**)&gauss_weights);
     4026
     4027}
     4028/*}}}*/
     4029/*FUNCTION Tria::CreatePVectorDiagnosticHoriz {{{1*/
     4030void Tria::CreatePVectorDiagnosticHoriz( Vec pg){
     4031
     4032        int             i,j;
     4033
     4034        /* node data: */
     4035        const int    numgrids=3;
     4036        const int    numdof=2*numgrids;
     4037        const int    NDOF2=2;
     4038        double       xyz_list[numgrids][3];
     4039        int          doflist[numdof];
     4040        int          numberofdofspernode;
     4041       
     4042        /* parameters: */
     4043        double  plastic_stress;
     4044        double  slope[NDOF2];
     4045        double  driving_stress_baseline;
     4046
     4047        /* gaussian points: */
     4048        int     num_gauss,ig;
     4049        double* first_gauss_area_coord  =  NULL;
     4050        double* second_gauss_area_coord =  NULL;
     4051        double* third_gauss_area_coord  =  NULL;
     4052        double* gauss_weights           =  NULL;
     4053        double  gauss_weight;
     4054        double  gauss_l1l2l3[3];
     4055
     4056        /* Jacobian: */
     4057        double Jdet;
     4058
     4059        /*nodal functions: */
     4060        double l1l2l3[3];
     4061
     4062        /*element vector at the gaussian points: */
     4063        double  pe_g[numdof]={0.0};
     4064        double  pe_g_gaussian[numdof];
     4065
     4066        /*input parameters for structural analysis (diagnostic): */
     4067        double  thickness;
     4068
     4069        /*inputs: */
     4070        bool onwater;
     4071        int  drag_type;
     4072
     4073        /*retrieve inputs :*/
     4074        inputs->GetParameterValue(&onwater,ElementOnWaterEnum);
     4075        inputs->GetParameterValue(&drag_type,DragTypeEnum);
     4076
     4077        /*First, if we are on water, return empty vector: */
     4078        if(onwater)return;
     4079
     4080        /* Get node coordinates and dof list: */
     4081        GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
     4082        GetDofList(&doflist[0],&numberofdofspernode);
     4083
     4084
     4085        /* Get gaussian points and weights: */
     4086        GaussTria( &num_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &gauss_weights, 2); /*We need higher order because our load is order 2*/
     4087
     4088        /* Start  looping on the number of gaussian points: */
     4089        for (ig=0; ig<num_gauss; ig++){
     4090                /*Pick up the gaussian point: */
     4091                gauss_weight=*(gauss_weights+ig);
     4092                gauss_l1l2l3[0]=*(first_gauss_area_coord+ig);
     4093                gauss_l1l2l3[1]=*(second_gauss_area_coord+ig);
     4094                gauss_l1l2l3[2]=*(third_gauss_area_coord+ig);
     4095
     4096                /*Compute thickness at gaussian point: */
     4097                inputs->GetParameterValue(&thickness, &gauss_l1l2l3[0],ThicknessEnum);
     4098                inputs->GetParameterDerivativeValue(&slope[0],&xyz_list[0][0],&gauss_l1l2l3[0],SurfaceEnum);
     4099               
     4100                /*In case we have plastic basal drag, compute plastic stress at gaussian point from k1, k2 and k3 fields in the
     4101                 * element itself: */
     4102                if(drag_type==1){
     4103                        inputs->GetParameterValue(&plastic_stress, &gauss_l1l2l3[0],DragCoefficientEnum);
     4104                }
     4105
     4106                /* Get Jacobian determinant: */
     4107                GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0],gauss_l1l2l3);
     4108               
     4109                 /*Get nodal functions: */
     4110                GetNodalFunctions(l1l2l3, gauss_l1l2l3);
     4111
     4112                /*Compute driving stress: */
     4113                driving_stress_baseline=matpar->GetRhoIce()*matpar->GetG()*thickness;
     4114
     4115                /*Build pe_g_gaussian vector: */
     4116                if(drag_type==1){
     4117                        for (i=0;i<numgrids;i++){
     4118                                for (j=0;j<NDOF2;j++){
     4119                                        pe_g_gaussian[i*NDOF2+j]=(-driving_stress_baseline*slope[j]-plastic_stress)*Jdet*gauss_weight*l1l2l3[i];
     4120                                }
     4121                        }
     4122                }
     4123                else {
     4124                        for (i=0;i<numgrids;i++){
     4125                                for (j=0;j<NDOF2;j++){
     4126                                        pe_g_gaussian[i*NDOF2+j]=-driving_stress_baseline*slope[j]*Jdet*gauss_weight*l1l2l3[i];
     4127                                }
     4128                        }
     4129                }
     4130
     4131                /*Add pe_g_gaussian vector to pe_g: */
     4132                for( i=0; i<numdof; i++)pe_g[i]+=pe_g_gaussian[i];
     4133
     4134        } //for (ig=0; ig<num_gauss; ig++)
     4135
     4136        /*Add pe_g to global vector pg: */
     4137        VecSetValues(pg,numdof,doflist,(const double*)pe_g,ADD_VALUES);
     4138
     4139        cleanup_and_return:
     4140        xfree((void**)&first_gauss_area_coord);
     4141        xfree((void**)&second_gauss_area_coord);
     4142        xfree((void**)&third_gauss_area_coord);
     4143        xfree((void**)&gauss_weights);
     4144
     4145}
     4146/*}}}*/
     4147/*FUNCTION Tria::CreatePVectorDiagnosticHutter{{{1*/
     4148void  Tria::CreatePVectorDiagnosticHutter(Vec pg){
     4149
     4150        /*Collapsed formulation: */
     4151        Sing*  sing=NULL;
     4152        int    i;
     4153
     4154        /*flags: */
     4155        bool onwater;
     4156
     4157        /*recover some inputs: */
     4158        inputs->GetParameterValue(&onwater,ElementOnWaterEnum);
     4159
     4160        /*If on water, skip: */
     4161        if(onwater)return;
     4162
     4163        /*Spawn 3 sing elements: */
     4164        for(i=0;i<3;i++){
     4165                sing=(Sing*)SpawnSing(i);
     4166                sing->CreatePVector(pg);
     4167        }
     4168
     4169        /*clean up*/
     4170        delete sing;
     4171
     4172}
     4173/*}}}*/
     4174/*FUNCTION Tria::CreatePVectorPrognostic {{{1*/
     4175void  Tria::CreatePVectorPrognostic(Vec pg){
     4176
     4177
     4178        /* local declarations */
     4179        int             i,j;
     4180
     4181        /* node data: */
     4182        const int    numgrids=3;
     4183        const int    NDOF1=1;
     4184        const int    numdof=NDOF1*numgrids;
     4185        double       xyz_list[numgrids][3];
     4186        int          doflist[numdof];
     4187        int          numberofdofspernode;
     4188
     4189        /* gaussian points: */
     4190        int     num_gauss,ig;
     4191        double* first_gauss_area_coord  =  NULL;
     4192        double* second_gauss_area_coord =  NULL;
     4193        double* third_gauss_area_coord  =  NULL;
     4194        double* gauss_weights           =  NULL;
     4195        double  gauss_weight;
     4196        double  gauss_l1l2l3[3];
     4197
     4198        /* matrix */
     4199        double pe_g[numgrids]={0.0};
     4200        double L[numgrids];
     4201        double Jdettria;
     4202
     4203        /*input parameters for structural analysis (diagnostic): */
     4204        double  accumulation_g;
     4205        double  melting_g;
     4206        double  thickness_g;
     4207
     4208        /*parameters: */
     4209        double  dt;
     4210
     4211        /*retrieve some parameters: */
     4212        this->parameters->FindParam(&dt,DtEnum);
     4213
     4214        /* Get node coordinates and dof list: */
     4215        GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
     4216        GetDofList(&doflist[0],&numberofdofspernode);
     4217
     4218        /* Get gaussian points and weights (make this a statically initialized list of points? fstd): */
     4219        GaussTria( &num_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &gauss_weights, 2);
     4220
     4221        /* Start  looping on the number of gaussian points: */
     4222        for (ig=0; ig<num_gauss; ig++){
     4223                /*Pick up the gaussian point: */
     4224                gauss_weight=*(gauss_weights+ig);
     4225                gauss_l1l2l3[0]=*(first_gauss_area_coord+ig);
     4226                gauss_l1l2l3[1]=*(second_gauss_area_coord+ig);
     4227                gauss_l1l2l3[2]=*(third_gauss_area_coord+ig);
     4228
     4229                /* Get Jacobian determinant: */
     4230                GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss_l1l2l3);
     4231
     4232                /*Get L matrix: */
     4233                GetL(&L[0], &xyz_list[0][0], gauss_l1l2l3,numberofdofspernode);
     4234
     4235                /* Get accumulation, melting and thickness at gauss point */
     4236                inputs->GetParameterValue(&accumulation_g, &gauss_l1l2l3[0],AccumulationRateEnum);
     4237                inputs->GetParameterValue(&melting_g, &gauss_l1l2l3[0],MeltingRateEnum);
     4238                inputs->GetParameterValue(&thickness_g, &gauss_l1l2l3[0],ThicknessEnum);
     4239
     4240                /* Add value into pe_g: */
     4241                for( i=0; i<numdof; i++) pe_g[i]+=Jdettria*gauss_weight*(thickness_g+dt*(accumulation_g-melting_g))*L[i];
     4242
     4243        } // for (ig=0; ig<num_gauss; ig++)
     4244
     4245        /*Add pe_g to global matrix Kgg: */
     4246        VecSetValues(pg,numdof,doflist,(const double*)pe_g,ADD_VALUES);
     4247
     4248cleanup_and_return:
     4249        xfree((void**)&first_gauss_area_coord);
     4250        xfree((void**)&second_gauss_area_coord);
     4251        xfree((void**)&third_gauss_area_coord);
     4252        xfree((void**)&gauss_weights);
     4253
     4254}
     4255/*}}}*/
     4256/*FUNCTION Tria::CreatePVectorPrognostic2 {{{1*/
     4257void  Tria::CreatePVectorPrognostic2(Vec pg){
     4258
     4259        /* local declarations */
     4260        int             i,j;
     4261
     4262        /* node data: */
     4263        const int    numgrids=3;
     4264        const int    NDOF1=1;
     4265        const int    numdof=NDOF1*numgrids;
     4266        double       xyz_list[numgrids][3];
     4267        int          doflist[numdof];
     4268        int          numberofdofspernode;
     4269
     4270        /* gaussian points: */
     4271        int     num_gauss,ig;
     4272        double* first_gauss_area_coord  =  NULL;
     4273        double* second_gauss_area_coord =  NULL;
     4274        double* third_gauss_area_coord  =  NULL;
     4275        double* gauss_weights           =  NULL;
     4276        double  gauss_weight;
     4277        double  gauss_l1l2l3[3];
     4278
     4279        /* matrix */
     4280        double pe_g[numgrids]={0.0};
     4281        double L[numgrids];
     4282        double Jdettria;
     4283
     4284        /*input parameters for structural analysis (diagnostic): */
     4285        double  accumulation_g;
     4286        double  melting_g;
     4287        double  thickness_g;
     4288        double  dt;
     4289
     4290        /*retrieve some parameters: */
     4291        this->parameters->FindParam(&dt,DtEnum);
     4292
     4293        /* Get node coordinates and dof list: */
     4294        GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
     4295        GetDofList(&doflist[0],&numberofdofspernode);
     4296
     4297        /* Get gaussian points and weights (make this a statically initialized list of points? fstd): */
     4298        GaussTria( &num_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &gauss_weights, 2);
     4299
     4300        /* Start  looping on the number of gaussian points: */
     4301        for (ig=0; ig<num_gauss; ig++){
     4302                /*Pick up the gaussian point: */
     4303                gauss_weight=*(gauss_weights+ig);
     4304                gauss_l1l2l3[0]=*(first_gauss_area_coord+ig);
     4305                gauss_l1l2l3[1]=*(second_gauss_area_coord+ig);
     4306                gauss_l1l2l3[2]=*(third_gauss_area_coord+ig);
     4307
     4308                /* Get Jacobian determinant: */
     4309                GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss_l1l2l3);
     4310
     4311                /*Get L matrix: */
     4312                GetL(&L[0], &xyz_list[0][0], gauss_l1l2l3,numberofdofspernode);
     4313
     4314                /* Get accumulation, melting and thickness at gauss point */
     4315                inputs->GetParameterValue(&accumulation_g, &gauss_l1l2l3[0],AccumulationRateEnum);
     4316                inputs->GetParameterValue(&melting_g, &gauss_l1l2l3[0],MeltingRateEnum);
     4317                inputs->GetParameterValue(&thickness_g, &gauss_l1l2l3[0],ThicknessEnum);
     4318
     4319                /* Add value into pe_g: */
     4320                for( i=0; i<numdof; i++) pe_g[i]+=Jdettria*gauss_weight*(thickness_g+dt*(accumulation_g-melting_g))*L[i];
     4321
     4322        } // for (ig=0; ig<num_gauss; ig++)
     4323
     4324        /*Add pe_g to global matrix Kgg: */
     4325        VecSetValues(pg,numdof,doflist,(const double*)pe_g,ADD_VALUES);
     4326
     4327cleanup_and_return:
     4328        xfree((void**)&first_gauss_area_coord);
     4329        xfree((void**)&second_gauss_area_coord);
     4330        xfree((void**)&third_gauss_area_coord);
     4331        xfree((void**)&gauss_weights);
     4332
     4333}
     4334/*}}}*/
     4335/*FUNCTION Tria::CreatePVectorSlopeCompute {{{1*/
     4336
     4337void Tria::CreatePVectorSlopeCompute( Vec pg){
     4338
     4339        int             i,j;
     4340
     4341        /* node data: */
     4342        const int    numgrids=3;
     4343        const int    NDOF1=1;
     4344        const int    numdof=NDOF1*numgrids;
     4345        double       xyz_list[numgrids][3];
     4346        int          doflist[numdof];
     4347        int          numberofdofspernode;
     4348       
     4349        /* gaussian points: */
     4350        int     num_gauss,ig;
     4351        double* first_gauss_area_coord  =  NULL;
     4352        double* second_gauss_area_coord =  NULL;
     4353        double* third_gauss_area_coord  =  NULL;
     4354        double* gauss_weights           =  NULL;
     4355        double  gauss_weight;
     4356        double  gauss_l1l2l3[3];
     4357
     4358        /* Jacobian: */
     4359        double Jdet;
     4360
     4361        /*nodal functions: */
     4362        double l1l2l3[3];
     4363
     4364        /*element vector at the gaussian points: */
     4365        double  pe_g[numdof]={0.0};
     4366        double  pe_g_gaussian[numdof];
     4367        double  slope[2];
     4368        int sub_analysis_type;
     4369
     4370        /*retrive parameters: */
     4371        parameters->FindParam(&sub_analysis_type,AnalysisTypeEnum);
     4372
     4373        /* Get node coordinates and dof list: */
     4374        GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
     4375        GetDofList(&doflist[0],&numberofdofspernode);
     4376
     4377
     4378        /* Get gaussian points and weights: */
     4379        GaussTria( &num_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &gauss_weights, 2); /*We need higher order because our load is order 2*/
     4380
     4381
     4382        /* Start  looping on the number of gaussian points: */
     4383        for (ig=0; ig<num_gauss; ig++){
     4384                /*Pick up the gaussian point: */
     4385                gauss_weight=*(gauss_weights+ig);
     4386                gauss_l1l2l3[0]=*(first_gauss_area_coord+ig);
     4387                gauss_l1l2l3[1]=*(second_gauss_area_coord+ig);
     4388                gauss_l1l2l3[2]=*(third_gauss_area_coord+ig);
     4389
     4390                if ( (sub_analysis_type==SurfaceSlopeXAnalysisEnum) || (sub_analysis_type==SurfaceSlopeYAnalysisEnum)){
     4391                        inputs->GetParameterDerivativeValue(&slope[0],&xyz_list[0][0],&gauss_l1l2l3[0],SurfaceEnum);
     4392                }
     4393                if ( (sub_analysis_type==BedSlopeXAnalysisEnum) || (sub_analysis_type==BedSlopeYAnalysisEnum)){
     4394                        inputs->GetParameterDerivativeValue(&slope[0],&xyz_list[0][0],&gauss_l1l2l3[0],BedEnum);
     4395                }
     4396
     4397                /* Get Jacobian determinant: */
     4398                GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0],gauss_l1l2l3);
     4399               
     4400                 /*Get nodal functions: */
     4401                GetNodalFunctions(l1l2l3, gauss_l1l2l3);
     4402
     4403                /*Build pe_g_gaussian vector: */
     4404                if ( (sub_analysis_type==SurfaceSlopeXAnalysisEnum) || (sub_analysis_type==BedSlopeXAnalysisEnum)){
     4405                        for(i=0;i<numdof;i++) pe_g_gaussian[i]=Jdet*gauss_weight*slope[0]*l1l2l3[i];
     4406                }
     4407                if ( (sub_analysis_type==SurfaceSlopeYAnalysisEnum) || (sub_analysis_type==BedSlopeYAnalysisEnum)){
     4408                        for(i=0;i<numdof;i++) pe_g_gaussian[i]=Jdet*gauss_weight*slope[1]*l1l2l3[i];
     4409                }
     4410
     4411                /*Add pe_g_gaussian vector to pe_g: */
     4412                for( i=0; i<numdof; i++)pe_g[i]+=pe_g_gaussian[i];
     4413
     4414        } //for (ig=0; ig<num_gauss; ig++)
     4415
     4416        /*Add pe_g to global vector pg: */
     4417        VecSetValues(pg,numdof,doflist,(const double*)pe_g,ADD_VALUES);
     4418
     4419        cleanup_and_return:
     4420        xfree((void**)&first_gauss_area_coord);
     4421        xfree((void**)&second_gauss_area_coord);
     4422        xfree((void**)&third_gauss_area_coord);
     4423        xfree((void**)&gauss_weights);
     4424
     4425}
     4426/*}}}*/
     4427/*FUNCTION Tria::CreatePVectorThermalShelf {{{1*/
     4428void Tria::CreatePVectorThermalShelf( Vec pg){
     4429
     4430        int i,found;
     4431       
     4432        const int  numgrids=3;
     4433        const int  NDOF1=1;
     4434        const int  numdof=numgrids*NDOF1;
     4435        int        doflist[numdof];
     4436        int        numberofdofspernode;
     4437        double       xyz_list[numgrids][3];
     4438
     4439        double mixed_layer_capacity;
     4440        double thermal_exchange_velocity;
     4441        double rho_water;
     4442        double rho_ice;
     4443        double heatcapacity;
     4444        double beta;
     4445        double meltingpoint;
     4446
     4447        /*inputs: */
     4448        double dt;
     4449        double pressure;
     4450
     4451        /* gaussian points: */
     4452        int     num_area_gauss,ig;
     4453        double* gauss_weights  =  NULL;
     4454        double* first_gauss_area_coord  =  NULL;
     4455        double* second_gauss_area_coord =  NULL;
     4456        double* third_gauss_area_coord  =  NULL;
     4457        double  gauss_weight;
     4458        double  gauss_coord[3];
     4459        int     dofs1[1]={0};
     4460
     4461        /*matrices: */
     4462        double  Jdet;
     4463        double  P_terms[numdof]={0.0};
     4464        double  l1l2l3[numgrids];
     4465
     4466        double  t_pmp;
     4467        double  scalar_ocean;
     4468
     4469        /* Get node coordinates and dof list: */
     4470        GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
     4471        GetDofList(&doflist[0],&numberofdofspernode);
     4472
     4473        //recover material parameters
     4474        mixed_layer_capacity=matpar->GetMixedLayerCapacity();
     4475        thermal_exchange_velocity=matpar->GetThermalExchangeVelocity();
     4476        rho_water=matpar->GetRhoWater();
     4477        rho_ice=matpar->GetRhoIce();
     4478        heatcapacity=matpar->GetHeatCapacity();
     4479        beta=matpar->GetBeta();
     4480        meltingpoint=matpar->GetMeltingPoint();
     4481       
     4482        /*retrieve some solution parameters: */
     4483        this->parameters->FindParam(&dt,DtEnum);
     4484
     4485        /* Ice/ocean heat exchange flux on ice shelf base */
     4486
     4487        GaussTria (&num_area_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &gauss_weights, 2);
     4488
     4489        /* Start looping on the number of gauss 2d (nodes on the bedrock) */
     4490        for (ig=0; ig<num_area_gauss; ig++){
     4491                gauss_weight=*(gauss_weights+ig);
     4492                gauss_coord[0]=*(first_gauss_area_coord+ig);
     4493                gauss_coord[1]=*(second_gauss_area_coord+ig);
     4494                gauss_coord[2]=*(third_gauss_area_coord+ig);
     4495
     4496                //Get the Jacobian determinant
     4497                GetJacobianDeterminant3d(&Jdet, &xyz_list[0][0], gauss_coord);
     4498
     4499                /*Get nodal functions values: */
     4500                GetNodalFunctions(&l1l2l3[0], gauss_coord);
     4501
     4502                /*Get geothermal flux and basal friction */
     4503                inputs->GetParameterValue(&pressure, &gauss_coord[0],PressureEnum);
     4504                t_pmp=meltingpoint-beta*pressure;
     4505
     4506                /*Calculate scalar parameter*/
     4507                scalar_ocean=gauss_weight*Jdet*rho_water*mixed_layer_capacity*thermal_exchange_velocity*(t_pmp)/(heatcapacity*rho_ice);
     4508                if(dt){
     4509                        scalar_ocean=dt*scalar_ocean;
     4510                }
     4511
     4512                for(i=0;i<3;i++){
     4513                        P_terms[i]+=scalar_ocean*l1l2l3[i];
     4514                }
     4515        }
     4516
     4517        /*Add pe_g to global vector pg: */
     4518        VecSetValues(pg,numdof,doflist,(const double*)P_terms,ADD_VALUES);
     4519
     4520        cleanup_and_return:
     4521        xfree((void**)&first_gauss_area_coord);
     4522        xfree((void**)&second_gauss_area_coord);
     4523        xfree((void**)&third_gauss_area_coord);
     4524        xfree((void**)&gauss_weights);
     4525
     4526}
     4527/*}}}*/
     4528/*FUNCTION Tria::CreatePVectorThermalSheet {{{1*/
     4529void Tria::CreatePVectorThermalSheet( Vec pg){
     4530
     4531        int i,found;
     4532       
     4533        const int  numgrids=3;
     4534        const int  NDOF1=1;
     4535        const int  numdof=numgrids*NDOF1;
     4536        int        doflist[numdof];
     4537        int        numberofdofspernode;
     4538        double       xyz_list[numgrids][3];
     4539
     4540        double rho_ice;
     4541        double heatcapacity;
     4542
     4543        /*inputs: */
     4544        double dt;
     4545        double pressure_list[3];
     4546        double pressure;
     4547        int    drag_type;
     4548        double basalfriction;
     4549        Friction* friction=NULL;
     4550        double alpha2,vx,vy;
     4551        double geothermalflux_value;
     4552
     4553        /* gaussian points: */
     4554        int     num_area_gauss,ig;
     4555        double* gauss_weights  =  NULL;
     4556        double* first_gauss_area_coord  =  NULL;
     4557        double* second_gauss_area_coord =  NULL;
     4558        double* third_gauss_area_coord  =  NULL;
     4559        double  gauss_weight;
     4560        double  gauss_coord[3];
     4561
     4562        /*matrices: */
     4563        double  Jdet;
     4564        double  P_terms[numdof]={0.0};
     4565        double  l1l2l3[numgrids];
     4566        double  scalar;
     4567
     4568        int analysis_type;
     4569
     4570        /*retrive parameters: */
     4571        parameters->FindParam(&analysis_type,AnalysisTypeEnum);
     4572
     4573       
     4574        /* Get node coordinates and dof list: */
     4575        GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
     4576        GetDofList(&doflist[0],&numberofdofspernode);
     4577
     4578        //recover material parameters
     4579        rho_ice=matpar->GetRhoIce();
     4580        heatcapacity=matpar->GetHeatCapacity();
     4581
     4582        /*retrieve some parameters: */
     4583        this->parameters->FindParam(&dt,DtEnum);
     4584
     4585        /*Build frictoin element, needed later: */
     4586        inputs->GetParameterValue(&drag_type,DragTypeEnum);
     4587        if (drag_type!=2)ISSMERROR(" non-viscous friction not supported yet!");
     4588        friction=new Friction("3d",inputs,matpar,analysis_type);
     4589       
     4590        /* Ice/ocean heat exchange flux on ice shelf base */
     4591        GaussTria (&num_area_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &gauss_weights, 2);
     4592
     4593        /* Start looping on the number of gauss 2d (nodes on the bedrock) */
     4594        for (ig=0; ig<num_area_gauss; ig++){
     4595                gauss_weight=*(gauss_weights+ig);
     4596                gauss_coord[0]=*(first_gauss_area_coord+ig);
     4597                gauss_coord[1]=*(second_gauss_area_coord+ig);
     4598                gauss_coord[2]=*(third_gauss_area_coord+ig);
     4599
     4600                //Get the Jacobian determinant
     4601                GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0], gauss_coord);
     4602
     4603                /*Get nodal functions values: */
     4604                GetNodalFunctions(&l1l2l3[0], gauss_coord);
     4605
     4606                /*Get geothermal flux and basal friction */
     4607                inputs->GetParameterValue(&geothermalflux_value, &gauss_coord[0],GeothermalFluxEnum);
     4608       
     4609                friction->GetAlpha2(&alpha2,&gauss_coord[0],VxEnum,VyEnum,VzEnum);
     4610                inputs->GetParameterValue(&vx, &gauss_coord[0],VxEnum);
     4611                inputs->GetParameterValue(&vy, &gauss_coord[0],VyEnum);
     4612                basalfriction= alpha2*(pow(vx,(double)2.0)+pow(vy,(double)2.0));
     4613               
     4614                /*Calculate scalar parameter*/
     4615                scalar=gauss_weight*Jdet*(basalfriction+geothermalflux_value)/(heatcapacity*rho_ice);
     4616                if(dt){
     4617                        scalar=dt*scalar;
     4618                }
     4619
     4620                for(i=0;i<3;i++){
     4621                        P_terms[i]+=scalar*l1l2l3[i];
     4622                }
     4623        }
     4624
     4625        /*Add pe_g to global vector pg: */
     4626        VecSetValues(pg,numdof,doflist,(const double*)P_terms,ADD_VALUES);
     4627
     4628        cleanup_and_return:
     4629        xfree((void**)&first_gauss_area_coord);
     4630        xfree((void**)&second_gauss_area_coord);
     4631        xfree((void**)&third_gauss_area_coord);
     4632        xfree((void**)&gauss_weights);
     4633        delete friction;
     4634
     4635}
     4636/*}}}*/
     4637/*FUNCTION Tria::GetArea {{{1*/
     4638double Tria::GetArea(void){
     4639
     4640        double area=0;
     4641        const int    numgrids=3;
     4642        double xyz_list[numgrids][3];
     4643        double x1,y1,x2,y2,x3,y3;
     4644
     4645        /*Get xyz list: */
     4646        GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
     4647        x1=xyz_list[0][0]; y1=xyz_list[0][1];
     4648        x2=xyz_list[1][0]; y2=xyz_list[1][1];
     4649        x3=xyz_list[2][0]; y3=xyz_list[2][1];
     4650 
     4651        return x2*y3 - y2*x3 + x1*y2 - y1*x2 + x3*y1 - y3*x1;
     4652}
     4653/*}}}*/
     4654/*FUNCTION Tria::GetAreaCoordinate {{{1*/
     4655double Tria::GetAreaCoordinate(double x, double y, int which_one){
     4656
     4657        double area=0;
     4658        const int    numgrids=3;
     4659        double xyz_list[numgrids][3];
     4660        double x1,y1,x2,y2,x3,y3;
     4661
     4662        /*Get area: */
     4663        area=this->GetArea();
     4664
     4665        /*Get xyz list: */
     4666        GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
     4667        x1=xyz_list[0][0]; y1=xyz_list[0][1];
     4668        x2=xyz_list[1][0]; y2=xyz_list[1][1];
     4669        x3=xyz_list[2][0]; y3=xyz_list[2][1];
     4670
     4671        if(which_one==1){
     4672                /*Get first area coordinate = det(x-x3  x2-x3 ; y-y3   y2-y3)/area*/
     4673                return ((x-x3)*(y2-y3)-(x2-x3)*(y-y3))/area;
     4674        }
     4675        else if(which_one==2){
     4676                /*Get second area coordinate = det(x1-x3  x-x3 ; y1-y3   y-y3)/area*/
     4677                return ((x1-x3)*(y-y3)-(x-x3)*(y1-y3))/area;
     4678        }
     4679        else if(which_one==3){
     4680                /*Get third  area coordinate 1-area1-area2: */
     4681                return 1-((x-x3)*(y2-y3)-(x2-x3)*(y-y3))/area -((x1-x3)*(y-y3)-(x-x3)*(y1-y3))/area;
     4682        }
     4683        else ISSMERROR("%s%i%s\n"," error message: area coordinate ",which_one," done not exist!");
     4684}
     4685/*}}}*/
     4686/*FUNCTION Tria::GetB {{{1*/
     4687
     4688void Tria::GetB(double* B, double* xyz_list, double* gauss_l1l2l3){
     4689
     4690        /*Compute B  matrix. B=[B1 B2 B3] where Bi is of size 3*NDOF2.
     4691         * For grid i, Bi can be expressed in the actual coordinate system
     4692         * by:
     4693         *       Bi=[ dh/dx    0    ]
     4694         *                [   0    dh/dy  ]
     4695         *                [ 1/2*dh/dy  1/2*dh/dx  ]
     4696         * where h is the interpolation function for grid i.
     4697         *
     4698         * We assume B has been allocated already, of size: 3x(NDOF2*numgrids)
     4699         */
     4700       
     4701        int i;
     4702        const int NDOF2=2;
     4703        const int numgrids=3;
     4704
     4705        double dh1dh3[NDOF2][numgrids];
     4706
     4707
     4708        /*Get dh1dh2dh3 in actual coordinate system: */
     4709        GetNodalFunctionsDerivatives(&dh1dh3[0][0],xyz_list, gauss_l1l2l3);
     4710
     4711        /*Build B: */
     4712        for (i=0;i<numgrids;i++){
     4713                *(B+NDOF2*numgrids*0+NDOF2*i)=dh1dh3[0][i]; //B[0][NDOF2*i]=dh1dh3[0][i];
     4714                *(B+NDOF2*numgrids*0+NDOF2*i+1)=0;
     4715                *(B+NDOF2*numgrids*1+NDOF2*i)=0;
     4716                *(B+NDOF2*numgrids*1+NDOF2*i+1)=dh1dh3[1][i];
     4717                *(B+NDOF2*numgrids*2+NDOF2*i)=(float).5*dh1dh3[1][i];
     4718                *(B+NDOF2*numgrids*2+NDOF2*i+1)=(float).5*dh1dh3[0][i];
     4719        }
     4720}
     4721/*}}}*/
     4722/*FUNCTION Tria::GetB_prog {{{1*/
     4723
     4724void Tria::GetB_prog(double* B_prog, double* xyz_list, double* gauss_l1l2l3){
     4725
     4726        /*Compute B  matrix. B=[B1 B2 B3] where Bi is of size 3*NDOF2.
     4727         * For grid i, Bi can be expressed in the actual coordinate system
     4728         * by:
     4729         *       Bi=[ h ]
     4730         *                [ h ]
     4731         * where h is the interpolation function for grid i.
     4732         *
     4733         * We assume B_prog has been allocated already, of size: 2x(NDOF1*numgrids)
     4734         */
     4735
     4736        int i;
     4737        const int NDOF1=1;
     4738        const int numgrids=3;
     4739
     4740        double l1l2l3[numgrids];
     4741
     4742
     4743        /*Get dh1dh2dh3 in actual coordinate system: */
     4744        GetNodalFunctions(&l1l2l3[0],gauss_l1l2l3);
     4745
     4746        /*Build B_prog: */
     4747        for (i=0;i<numgrids;i++){
     4748                *(B_prog+NDOF1*numgrids*0+NDOF1*i)=l1l2l3[i];
     4749                *(B_prog+NDOF1*numgrids*1+NDOF1*i)=l1l2l3[i];
     4750        }
     4751}
     4752/*}}}*/
     4753/*FUNCTION Tria::GetBPrime {{{1*/
     4754
     4755void Tria::GetBPrime(double* Bprime, double* xyz_list, double* gauss_l1l2l3){
     4756
     4757        /*Compute B'  matrix. B'=[B1' B2' B3'] where Bi' is of size 3*NDOF2.
     4758         * For grid i, Bi' can be expressed in the actual coordinate system
     4759         * by:
     4760         *       Bi_prime=[ 2*dh/dx dh/dy ]
     4761         *                       [ dh/dx  2*dh/dy]
     4762         *                       [dh/dy dh/dx]
     4763         * where h is the interpolation function for grid i.
     4764         *
     4765         * We assume B' has been allocated already, of size: 3x(NDOF2*numgrids)
     4766         */
     4767       
     4768        int i;
     4769        const int NDOF2=2;
     4770        const int numgrids=3;
     4771
     4772        /*Same thing in the actual coordinate system: */
     4773        double dh1dh3[NDOF2][numgrids];
     4774
     4775
     4776        /*Get dh1dh2dh3 in actual coordinates system : */
     4777        GetNodalFunctionsDerivatives(&dh1dh3[0][0],xyz_list,gauss_l1l2l3);
     4778
     4779        /*Build B': */
     4780        for (i=0;i<numgrids;i++){
     4781                *(Bprime+NDOF2*numgrids*0+NDOF2*i)=2*dh1dh3[0][i];
     4782                *(Bprime+NDOF2*numgrids*0+NDOF2*i+1)=dh1dh3[1][i];
     4783                *(Bprime+NDOF2*numgrids*1+NDOF2*i)=dh1dh3[0][i];
     4784                *(Bprime+NDOF2*numgrids*1+NDOF2*i+1)=2*dh1dh3[1][i];
     4785                *(Bprime+NDOF2*numgrids*2+NDOF2*i)=dh1dh3[1][i];
     4786                *(Bprime+NDOF2*numgrids*2+NDOF2*i+1)=dh1dh3[0][i];
     4787        }
     4788}
     4789/*}}}*/
     4790/*FUNCTION Tria::GetBPrime_prog {{{1*/
     4791
     4792void Tria::GetBPrime_prog(double* Bprime_prog, double* xyz_list, double* gauss_l1l2l3){
     4793
     4794        /*Compute B'  matrix. B'=[B1' B2' B3'] where Bi' is of size 3*NDOF2.
     4795         * For grid i, Bi' can be expressed in the actual coordinate system
     4796         * by:
     4797         *       Bi_prime=[ dh/dx ]
     4798         *                       [ dh/dy ]
     4799         * where h is the interpolation function for grid i.
     4800         *
     4801         * We assume B' has been allocated already, of size: 3x(NDOF2*numgrids)
     4802         */
     4803
     4804        int i;
     4805        const int NDOF1=1;
     4806        const int NDOF2=2;
     4807        const int numgrids=3;
     4808
     4809        /*Same thing in the actual coordinate system: */
     4810        double dh1dh3[NDOF2][numgrids];
     4811
     4812        /*Get dh1dh2dh3 in actual coordinates system : */
     4813        GetNodalFunctionsDerivatives(&dh1dh3[0][0],xyz_list,gauss_l1l2l3);
     4814
     4815        /*Build B': */
     4816        for (i=0;i<numgrids;i++){
     4817                *(Bprime_prog+NDOF1*numgrids*0+NDOF1*i)=dh1dh3[0][i];
     4818                *(Bprime_prog+NDOF1*numgrids*1+NDOF1*i)=dh1dh3[1][i];
     4819        }
     4820}
     4821/*}}}*/
     4822/*FUNCTION Tria::GetDofList {{{1*/
     4823void  Tria::GetDofList(int* doflist,int* pnumberofdofspernode){
     4824
     4825        int i,j;
     4826        int doflist_per_node[MAXDOFSPERNODE];
     4827        int numberofdofspernode;
     4828
     4829        /*Some checks for debugging*/
     4830        ISSMASSERT(doflist);
     4831        ISSMASSERT(pnumberofdofspernode);
     4832        ISSMASSERT(nodes);
     4833
     4834        /*Build doflist from nodes*/
     4835        for(i=0;i<3;i++){
     4836                nodes[i]->GetDofList(&doflist_per_node[0],&numberofdofspernode);
     4837                for(j=0;j<numberofdofspernode;j++){
     4838                        doflist[i*numberofdofspernode+j]=doflist_per_node[j];
     4839                }
    51664840        }
    51674841
    51684842        /*Assign output pointers:*/
    5169         *prow=row;
    5170 }
    5171 /*FUNCTION Tria::MinVel(double* pminvel, bool process_units);{{{1*/
    5172 void  Tria::MinVel(double* pminvel, bool process_units){
     4843        *pnumberofdofspernode=numberofdofspernode;
     4844
     4845}
     4846/*}}}*/
     4847/*FUNCTION Tria::GetDofList1 {{{1*/
     4848void  Tria::GetDofList1(int* doflist){
    51734849
    51744850        int i;
    5175         int dim;
     4851        for(i=0;i<3;i++){
     4852                doflist[i]=nodes[i]->GetDofList1();
     4853        }
     4854
     4855}
     4856/*}}}*/
     4857/*FUNCTION Tria::GetJacobian {{{1*/
     4858void Tria::GetJacobian(double* J, double* xyz_list,double* gauss_l1l2l3){
     4859
     4860        /*The Jacobian is constant over the element, discard the gaussian points.
     4861         * J is assumed to have been allocated of size NDOF2xNDOF2.*/
     4862
     4863        const int NDOF2=2;
    51764864        const int numgrids=3;
    5177         double  gaussgrids[numgrids][3]={{1,0,0},{0,1,0},{0,0,1}};
    5178         double  vx_values[numgrids];
    5179         double  vy_values[numgrids];
    5180         double  vz_values[numgrids];
    5181         double  vel_values[numgrids];
    5182         double  minvel;
    5183 
    5184         /*retrieve dim parameter: */
    5185         parameters->FindParam(&dim,DimEnum);
    5186 
    5187         /*retrive velocity values at nodes */
    5188         inputs->GetParameterValues(&vx_values[0],&gaussgrids[0][0],numgrids,VxEnum);
    5189         inputs->GetParameterValues(&vy_values[0],&gaussgrids[0][0],numgrids,VyEnum);
    5190         if(dim==3) inputs->GetParameterValues(&vz_values[0],&gaussgrids[0][0],numgrids,VzEnum);
    5191 
    5192         /*now, compute minimum of velocity :*/
    5193         if(dim==2){
    5194                 for(i=0;i<numgrids;i++)vel_values[i]=sqrt(pow(vx_values[i],2)+pow(vy_values[i],2));
     4865        double x1,y1,x2,y2,x3,y3;
     4866       
     4867        x1=*(xyz_list+numgrids*0+0);
     4868        y1=*(xyz_list+numgrids*0+1);
     4869        x2=*(xyz_list+numgrids*1+0);
     4870        y2=*(xyz_list+numgrids*1+1);
     4871        x3=*(xyz_list+numgrids*2+0);
     4872        y3=*(xyz_list+numgrids*2+1);
     4873
     4874
     4875        *(J+NDOF2*0+0)=0.5*(x2-x1);
     4876        *(J+NDOF2*1+0)=SQRT3/6.0*(2*x3-x1-x2);
     4877        *(J+NDOF2*0+1)=0.5*(y2-y1);
     4878        *(J+NDOF2*1+1)=SQRT3/6.0*(2*y3-y1-y2);
     4879}
     4880/*}}}*/
     4881/*FUNCTION Tria::GetJacobianDeterminant2d {{{1*/
     4882void Tria::GetJacobianDeterminant2d(double*  Jdet, double* xyz_list,double* gauss_l1l2l3){
     4883
     4884        /*The Jacobian determinant is constant over the element, discard the gaussian points.
     4885         * J is assumed to have been allocated of size NDOF2xNDOF2.*/
     4886
     4887        double x1,x2,x3,y1,y2,y3;
     4888       
     4889        x1=*(xyz_list+3*0+0);
     4890        y1=*(xyz_list+3*0+1);
     4891        x2=*(xyz_list+3*1+0);
     4892        y2=*(xyz_list+3*1+1);
     4893        x3=*(xyz_list+3*2+0);
     4894        y3=*(xyz_list+3*2+1);
     4895
     4896
     4897        *Jdet=SQRT3/6.0*((x2-x1)*(y3-y1)-(y2-y1)*(x3-x1));
     4898
     4899
     4900        if(Jdet<0){
     4901                ISSMERROR("negative jacobian determinant!");
     4902        }
     4903       
     4904}
     4905/*}}}*/
     4906/*FUNCTION Tria::GetJacobianDeterminant3d {{{1*/
     4907void Tria::GetJacobianDeterminant3d(double*  Jdet, double* xyz_list,double* gauss_l1l2l3){
     4908
     4909        /*The Jacobian determinant is constant over the element, discard the gaussian points.
     4910         * J is assumed to have been allocated of size NDOF2xNDOF2.*/
     4911
     4912        double x1,x2,x3,y1,y2,y3,z1,z2,z3;
     4913       
     4914        x1=*(xyz_list+3*0+0);
     4915        y1=*(xyz_list+3*0+1);
     4916        z1=*(xyz_list+3*0+2);
     4917        x2=*(xyz_list+3*1+0);
     4918        y2=*(xyz_list+3*1+1);
     4919        z2=*(xyz_list+3*1+2);
     4920        x3=*(xyz_list+3*2+0);
     4921        y3=*(xyz_list+3*2+1);
     4922        z3=*(xyz_list+3*2+2);
     4923
     4924
     4925        *Jdet=SQRT3/6.0*pow(pow(((y2-y1)*(z3-z1)-(z2-z1)*(y3-y1)),2.0)+pow(((z2-z1)*(x3-x1)-(x2-x1)*(z3-z1)),2.0)+pow(((x2-x1)*(y3-y1)-(y2-y1)*(x3-x1)),2.0),0.5);
     4926
     4927        if(Jdet<0){
     4928                ISSMERROR("negative jacobian determinant!");
     4929        }
     4930       
     4931}
     4932/*}}}*/
     4933/*FUNCTION Tria::GetJacobianInvert {{{1*/
     4934void Tria::GetJacobianInvert(double*  Jinv, double* xyz_list,double* gauss_l1l2l3){
     4935
     4936        double Jdet;
     4937        const int NDOF2=2;
     4938        const int numgrids=3;
     4939
     4940        /*Call Jacobian routine to get the jacobian:*/
     4941        GetJacobian(Jinv, xyz_list, gauss_l1l2l3);
     4942
     4943        /*Invert Jacobian matrix: */
     4944        MatrixInverse(Jinv,NDOF2,NDOF2,NULL,0,&Jdet);
     4945
     4946}
     4947/*}}}*/
     4948/*FUNCTION Tria::GetL {{{1*/
     4949
     4950void Tria::GetL(double* L, double* xyz_list, double* gauss_l1l2l3,int numdof){
     4951
     4952        /*Compute L  matrix. L=[L1 L2 L3] where Li is square and of size numdof.
     4953         * For grid i, Li can be expressed in the actual coordinate system
     4954         * by:
     4955         *       numdof=1:
     4956         *       Li=h;
     4957         *       numdof=2:
     4958         *       Li=[ h    0    ]
     4959         *                [   0   h  ]
     4960         * where h is the interpolation function for grid i.
     4961         *
     4962         * We assume L has been allocated already, of size: numgrids (numdof=1), or numdofx(numdof*numgrids) (numdof=2)
     4963         */
     4964
     4965        int i;
     4966        const int NDOF2=2;
     4967        const int numgrids=3;
     4968
     4969        double l1l2l3[3];
     4970
     4971
     4972        /*Get l1l2l3 in actual coordinate system: */
     4973        GetNodalFunctions(l1l2l3, gauss_l1l2l3);
     4974
     4975#ifdef _DELUG_
     4976        for (i=0;i<3;i++){
     4977                printf("Node %i  h=%lf \n",i,l1l2l3[i]);
     4978        }
     4979#endif
     4980
     4981        /*Build L: */
     4982        if(numdof==1){
     4983                for (i=0;i<numgrids;i++){
     4984                        L[i]=l1l2l3[i];
     4985                }
    51954986        }
    51964987        else{
    5197                 for(i=0;i<numgrids;i++)vel_values[i]=sqrt(pow(vx_values[i],2)+pow(vy_values[i],2)+pow(vz_values[i],2));
    5198         }
    5199 
    5200         /*now, compute minimum:*/
    5201         minvel=vel_values[0];
    5202         for(i=1;i<numgrids;i++){
    5203                 if (vel_values[i]<minvel)minvel=vel_values[i];
    5204         }
     4988                for (i=0;i<numgrids;i++){
     4989                        *(L+numdof*numgrids*0+numdof*i)=l1l2l3[i]; //L[0][NDOF2*i]=dh1dh3[0][i];
     4990                        *(L+numdof*numgrids*0+numdof*i+1)=0;
     4991                        *(L+numdof*numgrids*1+numdof*i)=0;
     4992                        *(L+numdof*numgrids*1+numdof*i+1)=l1l2l3[i];
     4993                }
     4994        }
     4995}
     4996/*}}}*/
     4997/*FUNCTION Tria::GetNodalFunctions {{{1*/
     4998void Tria::GetNodalFunctions(double* l1l2l3, double* gauss_l1l2l3){
     4999       
     5000        /*This routine returns the values of the nodal functions  at the gaussian point.*/
     5001
     5002        /*First nodal function: */
     5003        l1l2l3[0]=gauss_l1l2l3[0];
     5004
     5005        /*Second nodal function: */
     5006        l1l2l3[1]=gauss_l1l2l3[1];
     5007
     5008        /*Third nodal function: */
     5009        l1l2l3[2]=gauss_l1l2l3[2];
     5010
     5011}
     5012/*}}}*/
     5013/*FUNCTION Tria::GetNodalFunctionsDerivatives {{{1*/
     5014void Tria::GetNodalFunctionsDerivatives(double* dh1dh3,double* xyz_list, double* gauss_l1l2l3){
     5015       
     5016        /*This routine returns the values of the nodal functions derivatives  (with respect to the
     5017         * actual coordinate system: */
     5018
     5019        int i;
     5020        const int NDOF2=2;
     5021        const int numgrids=3;
     5022
     5023        double dh1dh3_ref[NDOF2][numgrids];
     5024        double Jinv[NDOF2][NDOF2];
     5025
     5026
     5027        /*Get derivative values with respect to parametric coordinate system: */
     5028        GetNodalFunctionsDerivativesReference(&dh1dh3_ref[0][0], gauss_l1l2l3);
     5029
     5030        /*Get Jacobian invert: */
     5031        GetJacobianInvert(&Jinv[0][0], xyz_list, gauss_l1l2l3);
     5032
     5033        /*Build dh1dh3:
     5034         *
     5035         * [dhi/dx]= Jinv*[dhi/dr]
     5036         * [dhi/dy]       [dhi/ds]
     5037         */
     5038
     5039        for (i=0;i<numgrids;i++){
     5040                *(dh1dh3+numgrids*0+i)=Jinv[0][0]*dh1dh3_ref[0][i]+Jinv[0][1]*dh1dh3_ref[1][i];
     5041                *(dh1dh3+numgrids*1+i)=Jinv[1][0]*dh1dh3_ref[0][i]+Jinv[1][1]*dh1dh3_ref[1][i];
     5042        }
     5043
     5044}
     5045/*}}}*/
     5046/*FUNCTION Tria::GetNodalFunctionsDerivativesReference {{{1*/
     5047void Tria::GetNodalFunctionsDerivativesReference(double* dl1dl3,double* gauss_l1l2l3){
     5048       
     5049        /*This routine returns the values of the nodal functions derivatives  (with respect to the
     5050         * natural coordinate system) at the gaussian point. */
     5051
     5052        const int NDOF2=2;
     5053        const int numgrids=3;
     5054
     5055        /*First nodal function: */
     5056        *(dl1dl3+numgrids*0+0)=-0.5;
     5057        *(dl1dl3+numgrids*1+0)=-1.0/(2.0*SQRT3);
     5058
     5059        /*Second nodal function: */
     5060        *(dl1dl3+numgrids*0+1)=0.5;
     5061        *(dl1dl3+numgrids*1+1)=-1.0/(2.0*SQRT3);
     5062
     5063        /*Third nodal function: */
     5064        *(dl1dl3+numgrids*0+2)=0;
     5065        *(dl1dl3+numgrids*1+2)=1.0/SQRT3;
     5066
     5067}
     5068/*}}}*/
     5069/*FUNCTION Tria::GetParameterDerivativeValue {{{1*/
     5070void Tria::GetParameterDerivativeValue(double* p, double* plist,double* xyz_list, double* gauss_l1l2l3){
     5071         
     5072        const int NDOF2=2;
     5073        const int numgrids=3;
     5074        /*From node values of parameter p (plist[0],plist[1],plist[2]), return parameter derivative value at gaussian
     5075         * point specified by gauss_l1l2l3:
     5076         *   dp/dx=plist[0]*dh1/dx+plist[1]*dh2/dx+plist[2]*dh3/dx
     5077         *   dp/dx=plist[0]*dh1/dx+plist[1]*dh2/dx+plist[2]*dh3/dx
     5078         *
     5079         * p is a vector of size 2x1 already allocated.
     5080         */
     5081       
     5082        double dh1dh3[NDOF2][numgrids]; //nodal derivative functions in actual coordinate system.
     5083
     5084        /*Get dh1dh2dh3 in actual coordinate system: */
     5085        GetNodalFunctionsDerivatives(&dh1dh3[0][0],xyz_list, gauss_l1l2l3);
     5086
     5087        *(p+0)=plist[0]*dh1dh3[0][0]+plist[1]*dh1dh3[0][1]+plist[2]*dh1dh3[0][2];
     5088        *(p+1)=plist[0]*dh1dh3[1][0]+plist[1]*dh1dh3[1][1]+plist[2]*dh1dh3[1][2];
     5089
     5090}
     5091/*}}}*/
     5092/*FUNCTION Tria::GetParameterValue {{{1*/
     5093void Tria::GetParameterValue(double* pp, double* plist, double* gauss_l1l2l3){
     5094       
     5095        /*From node values of parameter p (plist[0],plist[1],plist[2]), return parameter value at gaussian
     5096         * point specifie by gauss_l1l2l3: */
     5097       
     5098        /*nodal functions: */
     5099        double l1l2l3[3];
     5100
     5101        /*output: */
     5102        double p;
     5103
     5104        GetNodalFunctions(l1l2l3, gauss_l1l2l3);
     5105
     5106        p=l1l2l3[0]*plist[0]+l1l2l3[1]*plist[1]+l1l2l3[2]*plist[2];
    52055107
    52065108        /*Assign output pointers:*/
    5207         *pminvel=minvel;
    5208 
    5209 }
    5210 /*}}}*/
    5211 /*FUNCTION Tria::MaxVel(double* pmaxvel, bool process_units);{{{1*/
    5212 void  Tria::MaxVel(double* pmaxvel, bool process_units){
     5109        *pp=p;
     5110}
     5111/*}}}*/
     5112/*FUNCTION Tria::GradjDragStokes {{{1*/
     5113void  Tria::GradjDragStokes(Vec gradient){
    52135114
    52145115        int i;
    5215         int dim;
    5216         const int numgrids=3;
    5217         double  gaussgrids[numgrids][3]={{1,0,0},{0,1,0},{0,0,1}};
    5218         double  vx_values[numgrids];
    5219         double  vy_values[numgrids];
    5220         double  vz_values[numgrids];
    5221         double  vel_values[numgrids];
    5222         double  maxvel;
    5223 
    5224         /*retrieve dim parameter: */
    5225         parameters->FindParam(&dim,DimEnum);
    5226 
    5227         /*retrive velocity values at nodes */
    5228         inputs->GetParameterValues(&vx_values[0],&gaussgrids[0][0],numgrids,VxEnum);
    5229         inputs->GetParameterValues(&vy_values[0],&gaussgrids[0][0],numgrids,VyEnum);
    5230         if(dim==3) inputs->GetParameterValues(&vz_values[0],&gaussgrids[0][0],numgrids,VzEnum);
    5231 
    5232         /*now, compute maximum of velocity :*/
    5233         if(dim==2){
    5234                 for(i=0;i<numgrids;i++)vel_values[i]=sqrt(pow(vx_values[i],2)+pow(vy_values[i],2));
    5235         }
    5236         else{
    5237                 for(i=0;i<numgrids;i++)vel_values[i]=sqrt(pow(vx_values[i],2)+pow(vy_values[i],2)+pow(vz_values[i],2));
    5238         }
    5239 
    5240         /*now, compute maximum:*/
    5241         maxvel=vel_values[0];
    5242         for(i=1;i<numgrids;i++){
    5243                 if (vel_values[i]>maxvel)maxvel=vel_values[i];
    5244         }
    5245 
    5246         /*Assign output pointers:*/
    5247         *pmaxvel=maxvel;
    5248 
    5249 }
    5250 /*}}}*/
    5251 /*FUNCTION Tria::MinVx(double* pminvx, bool process_units);{{{1*/
    5252 void  Tria::MinVx(double* pminvx, bool process_units){
     5116
     5117        /* node data: */
     5118        const int    numgrids=3;
     5119        const int    NDOF2=2;
     5120        double       xyz_list[numgrids][3];
     5121        int          doflist1[numgrids];
     5122        double       dh1dh3[NDOF2][numgrids];
     5123
     5124        /* grid data: */
     5125        double drag;
     5126        double alpha_complement;
     5127        Friction* friction=NULL;
     5128
     5129        /* gaussian points: */
     5130        int     num_gauss,ig;
     5131        double* first_gauss_area_coord  =  NULL;
     5132        double* second_gauss_area_coord =  NULL;
     5133        double* third_gauss_area_coord  =  NULL;
     5134        double* gauss_weights           =  NULL;
     5135        double  gauss_weight;
     5136        double  gauss_l1l2l3[3];
     5137        double  gaussgrids[numgrids][numgrids]={{1,0,0},{0,1,0},{0,0,1}};
     5138
     5139        /* parameters: */
     5140        double  vx,vy,vz;
     5141        double  lambda,mu,xi;
     5142        double  bed,thickness,Neff;
     5143        double  surface_normal[3];
     5144        double  bed_normal[3];
     5145        double  dk[NDOF2];
     5146
     5147        /*element vector at the gaussian points: */
     5148        double  grade_g[numgrids]={0.0};
     5149        double  grade_g_gaussian[numgrids];
     5150
     5151        /* Jacobian: */
     5152        double Jdet;
     5153
     5154        /*nodal functions: */
     5155        double l1l2l3[3];
     5156
     5157        /* strain rate: */
     5158        double epsilon[3]; /* epsilon=[exx,eyy,exy];*/
     5159
     5160        /*inputs: */
     5161        bool shelf;
     5162        int  drag_type;
     5163
     5164        /*parameters: */
     5165        double  cm_noisedmp;
     5166        double  cm_mindmp_slope;
     5167        double  cm_mindmp_value;
     5168        double  cm_maxdmp_value;
     5169        double  cm_maxdmp_slope;
     5170
     5171        int analysis_type;
     5172
     5173        /*retrive parameters: */
     5174        parameters->FindParam(&analysis_type,AnalysisTypeEnum);
     5175
     5176        /*retrieve inputs :*/
     5177        inputs->GetParameterValue(&shelf,ElementOnIceShelfEnum);
     5178        inputs->GetParameterValue(&drag_type,DragTypeEnum);
     5179
     5180        /*retrieve some parameters: */
     5181        this->parameters->FindParam(&cm_noisedmp,CmNoiseDmpEnum);
     5182        this->parameters->FindParam(&cm_mindmp_value,CmMinDmpValueEnum);
     5183        this->parameters->FindParam(&cm_mindmp_slope,CmMinDmpSlopeEnum);
     5184        this->parameters->FindParam(&cm_maxdmp_value,CmMaxDmpValueEnum);
     5185        this->parameters->FindParam(&cm_maxdmp_slope,CmMaxDmpSlopeEnum);
     5186
     5187        /*Get out if shelf*/
     5188        if(shelf)return;
     5189
     5190        /* Get node coordinates and dof list: */
     5191        GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
     5192        GetDofList1(&doflist1[0]);
     5193
     5194        /*Build frictoin element, needed later: */
     5195        inputs->GetParameterValue(&drag_type,DragTypeEnum);
     5196        friction=new Friction("2d",inputs,matpar,analysis_type);
     5197
     5198        /* Get gaussian points and weights (make this a statically initialized list of points? fstd): */
     5199        GaussTria( &num_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &gauss_weights, 4);
     5200
     5201        /* Start  looping on the number of gaussian points: */
     5202        for (ig=0; ig<num_gauss; ig++){
     5203                /*Pick up the gaussian point: */
     5204                gauss_weight=*(gauss_weights+ig);
     5205                gauss_l1l2l3[0]=*(first_gauss_area_coord+ig);
     5206                gauss_l1l2l3[1]=*(second_gauss_area_coord+ig);
     5207                gauss_l1l2l3[2]=*(third_gauss_area_coord+ig);
     5208
     5209                /*Recover alpha_complement and drag: */
     5210                if (drag_type==2) friction->GetAlphaComplement(&alpha_complement, gauss_l1l2l3,VxAverageEnum,VyAverageEnum);
     5211                else alpha_complement=0;
     5212                inputs->GetParameterValue(&drag, &gauss_l1l2l3[0],DragCoefficientEnum);
     5213
     5214                /*recover lambda mu and xi: */
     5215                inputs->GetParameterValue(&lambda, &gauss_l1l2l3[0],AdjointxEnum);
     5216                inputs->GetParameterValue(&mu, &gauss_l1l2l3[0],AdjointyEnum);
     5217                inputs->GetParameterValue(&xi, &gauss_l1l2l3[0],AdjointzEnum);
     5218
     5219                /*recover vx vy and vz: */
     5220                inputs->GetParameterValue(&vx, &gauss_l1l2l3[0],VxEnum);
     5221                inputs->GetParameterValue(&vy, &gauss_l1l2l3[0],VyEnum);
     5222                inputs->GetParameterValue(&vz, &gauss_l1l2l3[0],VzEnum);
     5223
     5224                /*Get normal vector to the bed */
     5225                SurfaceNormal(&surface_normal[0],xyz_list);
     5226
     5227                bed_normal[0]=-surface_normal[0]; //Program is for surface, so the normal to the bed is the opposite of the result
     5228                bed_normal[1]=-surface_normal[1];
     5229                bed_normal[2]=-surface_normal[2];
     5230
     5231                /* Get Jacobian determinant: */
     5232                GetJacobianDeterminant3d(&Jdet, &xyz_list[0][0],gauss_l1l2l3);
     5233
     5234                /* Get nodal functions value at gaussian point:*/
     5235                GetNodalFunctions(l1l2l3, gauss_l1l2l3);
     5236
     5237                /*Get nodal functions derivatives*/
     5238                GetNodalFunctionsDerivatives(&dh1dh3[0][0],&xyz_list[0][0],gauss_l1l2l3);
     5239
     5240                /*Get k derivative: dk/dx */
     5241                inputs->GetParameterDerivativeValue(&dk[0],&xyz_list[0][0],&gauss_l1l2l3[0],DragCoefficientEnum);
     5242
     5243                /*Build gradje_g_gaussian vector (actually -dJ/ddrag): */
     5244                for (i=0;i<numgrids;i++){
     5245                        //standard gradient dJ/dki
     5246                        grade_g_gaussian[i]=(
     5247                                                -lambda*(2*drag*alpha_complement*(vx - vz*bed_normal[0]*bed_normal[2]))
     5248                                                -mu    *(2*drag*alpha_complement*(vy - vz*bed_normal[1]*bed_normal[2]))
     5249                                                -xi    *(2*drag*alpha_complement*(-vx*bed_normal[0]*bed_normal[2]-vy*bed_normal[1]*bed_normal[2]))
     5250                                                )*Jdet*gauss_weight*l1l2l3[i];
     5251
     5252                        //Add regularization term
     5253                        grade_g_gaussian[i]+= - cm_noisedmp*Jdet*gauss_weight*(dh1dh3[0][i]*dk[0]+dh1dh3[1][i]*dk[1]);
     5254
     5255                        //min dampening
     5256                        if(drag<cm_mindmp_value){
     5257                                grade_g_gaussian[i]+= cm_mindmp_slope*Jdet*gauss_weight*l1l2l3[i];
     5258                        }
     5259
     5260                        //max dampening
     5261                        if(drag>cm_maxdmp_value){
     5262                                grade_g_gaussian[i]+= - cm_maxdmp_slope*Jdet*gauss_weight*l1l2l3[i];
     5263                        }
     5264                }
     5265
     5266                /*Add gradje_g_gaussian vector to gradje_g: */
     5267                for( i=0; i<numgrids; i++)grade_g[i]+=grade_g_gaussian[i];
     5268        }
     5269
     5270        /*Add grade_g to global vector gradient: */
     5271        VecSetValues(gradient,numgrids,doflist1,(const double*)grade_g,ADD_VALUES);
     5272
     5273        /*Add grade_g to the inputs of this element: */
     5274        this->inputs->AddInput(new TriaVertexInput(GradientEnum,&grade_g[0]));
     5275
     5276        cleanup_and_return:
     5277        xfree((void**)&first_gauss_area_coord);
     5278        xfree((void**)&second_gauss_area_coord);
     5279        xfree((void**)&third_gauss_area_coord);
     5280        xfree((void**)&gauss_weights);
     5281        delete friction;
     5282
     5283}
     5284/*}}}*/
     5285/*FUNCTION Tria::SetClone {{{1*/
     5286void  Tria::SetClone(int* minranks){
     5287
     5288        ISSMERROR("not implemented yet");
     5289}
     5290/*}}}1*/
     5291/*FUNCTION Tria::SpawnBeam {{{1*/
     5292void* Tria::SpawnBeam(int g0, int g1){
    52535293
    52545294        int i;
    5255         int dim;
    5256         const int numgrids=3;
    5257         double  gaussgrids[numgrids][numgrids]={{1,0,0},{0,1,0},{0,0,1}};
    5258         double  vx_values[numgrids];
    5259         double  minvx;
    5260 
    5261         /*retrieve dim parameter: */
    5262         parameters->FindParam(&dim,DimEnum);
    5263 
    5264         /*retrive velocity values at nodes */
    5265         inputs->GetParameterValues(&vx_values[0],&gaussgrids[0][0],numgrids,VxEnum);
    5266 
    5267         /*now, compute minimum:*/
    5268         minvx=vx_values[0];
    5269         for(i=1;i<numgrids;i++){
    5270                 if (vx_values[i]<minvx)minvx=vx_values[i];
    5271         }
    5272 
    5273         /*Assign output pointers:*/
    5274         *pminvx=minvx;
    5275 
    5276 }
    5277 /*}}}*/
    5278 /*FUNCTION Tria::MaxVx(double* pmaxvx, bool process_units);{{{1*/
    5279 void  Tria::MaxVx(double* pmaxvx, bool process_units){
     5295
     5296        /*out of grids g0,g1 and g2 from Tria, build a beam element: */
     5297        Beam* beam=NULL;
     5298        int indices[2];
     5299        int zero=0;
     5300        Parameters *beam_parameters = NULL;
     5301        Inputs     *beam_inputs     = NULL;
     5302
     5303        indices[0]=g0;
     5304        indices[1]=g1;
     5305
     5306        beam_parameters=this->parameters;
     5307        beam_inputs=(Inputs*)this->inputs->SpawnBeamInputs(indices);
     5308
     5309        beam=new Beam();
     5310        beam->id=this->id;
     5311        beam->inputs=beam_inputs;
     5312        beam->parameters=beam_parameters;
     5313
     5314        /*now deal with nodes, matice and matpar: */
     5315        beam->nodes=(Node**)xmalloc(2*sizeof(Node*));
     5316        for(i=0;i<2;i++)beam->nodes[i]=this->nodes[indices[i]];
     5317        beam->matice=this->matice;
     5318        beam->matpar=this->matpar;
     5319
     5320
     5321        return beam;
     5322}
     5323/*}}}*/
     5324/*FUNCTION Tria::SpawnSing {{{1*/
     5325void* Tria::SpawnSing(int index){
     5326
     5327        Sing* sing=NULL;
     5328        int zero=0;
     5329        Parameters *sing_parameters = NULL;
     5330        Inputs     *sing_inputs     = NULL;
     5331
     5332        sing_parameters=this->parameters;
     5333        sing_inputs=(Inputs*)this->inputs->SpawnSingInputs(index);
     5334
     5335        sing=new Sing();
     5336        sing->id=this->id;
     5337        sing->inputs=sing_inputs;
     5338        sing->parameters=sing_parameters;
     5339
     5340        /*now deal with node,matice and matpar: */
     5341        sing->node=this->nodes[index];
     5342        sing->matice=this->matice;
     5343        sing->matpar=this->matpar;
     5344       
     5345        return sing;
     5346}
     5347/*}}}*/
     5348/*FUNCTION Tria::SurfaceNormal{{{1*/
     5349
     5350void Tria::SurfaceNormal(double* surface_normal, double xyz_list[3][3]){
    52805351
    52815352        int i;
    5282         int dim;
    5283         const int numgrids=3;
    5284         double  gaussgrids[numgrids][numgrids]={{1,0,0},{0,1,0},{0,0,1}};
    5285         double  vx_values[numgrids];
    5286         double  maxvx;
    5287 
    5288         /*retrieve dim parameter: */
    5289         parameters->FindParam(&dim,DimEnum);
    5290 
    5291         /*retrive velocity values at nodes */
    5292         inputs->GetParameterValues(&vx_values[0],&gaussgrids[0][0],numgrids,VxEnum);
    5293 
    5294         /*now, compute maximum:*/
    5295         maxvx=vx_values[0];
    5296         for(i=1;i<numgrids;i++){
    5297                 if (vx_values[i]>maxvx)maxvx=vx_values[i];
    5298         }
    5299 
    5300         /*Assign output pointers:*/
    5301         *pmaxvx=maxvx;
    5302 
    5303 }
    5304 /*}}}*/
    5305 /*FUNCTION Tria::MaxAbsVx(double* pmaxabsvx, bool process_units);{{{1*/
    5306 void  Tria::MaxAbsVx(double* pmaxabsvx, bool process_units){
    5307 
    5308         int i;
    5309         int dim;
    5310         const int numgrids=3;
    5311         double  gaussgrids[numgrids][numgrids]={{1,0,0},{0,1,0},{0,0,1}};
    5312         double  vx_values[numgrids];
    5313         double  maxabsvx;
    5314 
    5315         /*retrieve dim parameter: */
    5316         parameters->FindParam(&dim,DimEnum);
    5317 
    5318         /*retrive velocity values at nodes */
    5319         inputs->GetParameterValues(&vx_values[0],&gaussgrids[0][0],numgrids,VxEnum);
    5320 
    5321         /*now, compute maximum:*/
    5322         maxabsvx=fabs(vx_values[0]);
    5323         for(i=1;i<numgrids;i++){
    5324                 if (fabs(vx_values[i])>maxabsvx)maxabsvx=fabs(vx_values[i]);
    5325         }
    5326 
    5327         /*Assign output pointers:*/
    5328         *pmaxabsvx=maxabsvx;
    5329 }
    5330 /*}}}*/
    5331 /*FUNCTION Tria::MinVy(double* pminvy, bool process_units);{{{1*/
    5332 void  Tria::MinVy(double* pminvy, bool process_units){
    5333 
    5334         int i;
    5335         int dim;
    5336         const int numgrids=3;
    5337         double  gaussgrids[numgrids][numgrids]={{1,0,0},{0,1,0},{0,0,1}};
    5338         double  vy_values[numgrids];
    5339         double  minvy;
    5340 
    5341         /*retrieve dim parameter: */
    5342         parameters->FindParam(&dim,DimEnum);
    5343 
    5344         /*retrive velocity values at nodes */
    5345         inputs->GetParameterValues(&vy_values[0],&gaussgrids[0][0],numgrids,VyEnum);
    5346 
    5347         /*now, compute minimum:*/
    5348         minvy=vy_values[0];
    5349         for(i=1;i<numgrids;i++){
    5350                 if (vy_values[i]<minvy)minvy=vy_values[i];
    5351         }
    5352 
    5353         /*Assign output pointers:*/
    5354         *pminvy=minvy;
    5355 
    5356 }
    5357 /*}}}*/
    5358 /*FUNCTION Tria::MaxVy(double* pmaxvy, bool process_units);{{{1*/
    5359 void  Tria::MaxVy(double* pmaxvy, bool process_units){
    5360 
    5361         int i;
    5362         int dim;
    5363         const int numgrids=3;
    5364         double  gaussgrids[numgrids][numgrids]={{1,0,0},{0,1,0},{0,0,1}};
    5365         double  vy_values[numgrids];
    5366         double  maxvy;
    5367 
    5368         /*retrieve dim parameter: */
    5369         parameters->FindParam(&dim,DimEnum);
    5370 
    5371         /*retrive velocity values at nodes */
    5372         inputs->GetParameterValues(&vy_values[0],&gaussgrids[0][0],numgrids,VyEnum);
    5373 
    5374         /*now, compute maximum:*/
    5375         maxvy=vy_values[0];
    5376         for(i=1;i<numgrids;i++){
    5377                 if (vy_values[i]>maxvy)maxvy=vy_values[i];
    5378         }
    5379 
    5380         /*Assign output pointers:*/
    5381         *pmaxvy=maxvy;
    5382 
    5383 }
    5384 /*}}}*/
    5385 /*FUNCTION Tria::MaxAbsVy(double* pmaxabsvy, bool process_units);{{{1*/
    5386 void  Tria::MaxAbsVy(double* pmaxabsvy, bool process_units){
    5387 
    5388         int i;
    5389         int dim;
    5390         const int numgrids=3;
    5391         double  gaussgrids[numgrids][numgrids]={{1,0,0},{0,1,0},{0,0,1}};
    5392         double  vy_values[numgrids];
    5393         double  maxabsvy;
    5394 
    5395         /*retrieve dim parameter: */
    5396         parameters->FindParam(&dim,DimEnum);
    5397 
    5398         /*retrive velocity values at nodes */
    5399         inputs->GetParameterValues(&vy_values[0],&gaussgrids[0][0],numgrids,VyEnum);
    5400 
    5401         /*now, compute maximum:*/
    5402         maxabsvy=fabs(vy_values[0]);
    5403         for(i=1;i<numgrids;i++){
    5404                 if (fabs(vy_values[i])>maxabsvy)maxabsvy=fabs(vy_values[i]);
    5405         }
    5406 
    5407         /*Assign output pointers:*/
    5408         *pmaxabsvy=maxabsvy;
    5409 }
    5410 /*}}}*/
    5411 /*FUNCTION Tria::MinVz(double* pminvz, bool process_units);{{{1*/
    5412 void  Tria::MinVz(double* pminvz, bool process_units){
    5413 
    5414         int i;
    5415         int dim;
    5416         const int numgrids=3;
    5417         double  gaussgrids[numgrids][numgrids]={{1,0,0},{0,1,0},{0,0,1}};
    5418         double  vz_values[numgrids];
    5419         double  minvz;
    5420 
    5421         /*retrieve dim parameter: */
    5422         parameters->FindParam(&dim,DimEnum);
    5423 
    5424         /*retrive velocity values at nodes */
    5425         inputs->GetParameterValues(&vz_values[0],&gaussgrids[0][0],numgrids,VzEnum);
    5426 
    5427         /*now, compute minimum:*/
    5428         minvz=vz_values[0];
    5429         for(i=1;i<numgrids;i++){
    5430                 if (vz_values[i]<minvz)minvz=vz_values[i];
    5431         }
    5432 
    5433         /*Assign output pointers:*/
    5434         *pminvz=minvz;
    5435 
    5436 }
    5437 /*}}}*/
    5438 /*FUNCTION Tria::MaxVz(double* pmaxvz, bool process_units);{{{1*/
    5439 void  Tria::MaxVz(double* pmaxvz, bool process_units){
    5440 
    5441         int i;
    5442         int dim;
    5443         const int numgrids=3;
    5444         double  gaussgrids[numgrids][numgrids]={{1,0,0},{0,1,0},{0,0,1}};
    5445         double  vz_values[numgrids];
    5446         double  maxvz;
    5447 
    5448         /*retrieve dim parameter: */
    5449         parameters->FindParam(&dim,DimEnum);
    5450 
    5451         /*retrive velocity values at nodes */
    5452         inputs->GetParameterValues(&vz_values[0],&gaussgrids[0][0],numgrids,VzEnum);
    5453 
    5454         /*now, compute maximum:*/
    5455         maxvz=vz_values[0];
    5456         for(i=1;i<numgrids;i++){
    5457                 if (vz_values[i]>maxvz)maxvz=vz_values[i];
    5458         }
    5459 
    5460         /*Assign output pointers:*/
    5461         *pmaxvz=maxvz;
    5462 
    5463 }
    5464 /*}}}*/
    5465 /*FUNCTION Tria::MaxAbsVz(double* pmaxabsvz, bool process_units);{{{1*/
    5466 void  Tria::MaxAbsVz(double* pmaxabsvz, bool process_units){
    5467 
    5468         int i;
    5469         int dim;
    5470         const int numgrids=3;
    5471         double  gaussgrids[numgrids][numgrids]={{1,0,0},{0,1,0},{0,0,1}};
    5472         double  vz_values[numgrids];
    5473         double  maxabsvz;
    5474 
    5475         /*retrieve dim parameter: */
    5476         parameters->FindParam(&dim,DimEnum);
    5477 
    5478         /*retrive velocity values at nodes */
    5479         inputs->GetParameterValues(&vz_values[0],&gaussgrids[0][0],numgrids,VzEnum);
    5480 
    5481         /*now, compute maximum:*/
    5482         maxabsvz=fabs(vz_values[0]);
    5483         for(i=1;i<numgrids;i++){
    5484                 if (fabs(vz_values[i])>maxabsvz)maxabsvz=fabs(vz_values[i]);
    5485         }
    5486 
    5487         /*Assign output pointers:*/
    5488         *pmaxabsvz=maxabsvz;
    5489 }
    5490 /*}}}*/
    5491 /*FUNCTION Tria::InputDuplicate(int original_enum,int new_enum){{{1*/
    5492 void  Tria::InputDuplicate(int original_enum,int new_enum){
    5493 
    5494         Input* original=NULL;
    5495         Input* copy=NULL;
    5496 
    5497         /*Make a copy of the original input: */
    5498         original=(Input*)this->inputs->GetInput(original_enum);
    5499         copy=(Input*)original->copy();
    5500 
    5501         /*Change copy enum to reinitialized_enum: */
    5502         copy->ChangeEnum(new_enum);
    5503 
    5504         /*Add copy into inputs, it will wipe off the one already there: */
    5505         inputs->AddObject((Input*)copy);
    5506 }
    5507 /*}}}*/
    5508 /*FUNCTION Tria::InputScale(int enum_type,double scale_factor){{{1*/
    5509 void  Tria::InputScale(int enum_type,double scale_factor){
    5510 
    5511         Input* input=NULL;
    5512 
    5513         /*Make a copy of the original input: */
    5514         input=(Input*)this->inputs->GetInput(enum_type);
    5515 
    5516         /*Scale: */
    5517         input->Scale(scale_factor);
    5518 }
    5519 /*}}}*/
    5520 /*FUNCTION Tria::InputAXPY(int YEnum, double scalar, int XEnum);{{{1*/
    5521 void  Tria::InputAXPY(int YEnum, double scalar, int XEnum){
    5522 
    5523         Input* xinput=NULL;
    5524         Input* yinput=NULL;
    5525 
    5526         /*Find x and y inputs: */
    5527         xinput=(Input*)this->inputs->GetInput(XEnum);
    5528         yinput=(Input*)this->inputs->GetInput(YEnum);
    5529 
    5530         /*some checks: */
    5531         if(!xinput || !yinput) ISSMERROR("%s%s%s%s%s"," input ",EnumAsString(XEnum)," or input ",EnumAsString(YEnum)," could not be found!");
    5532 
    5533         /*Scale: */
    5534         yinput->AXPY(xinput,scalar);
    5535 }
    5536 /*}}}*/
    5537 /*FUNCTION Tria::InputControlConstrain(int control_type, double cm_min, double cm_max){{{1*/
    5538 void  Tria::InputControlConstrain(int control_type, double cm_min, double cm_max){
    5539 
    5540         Input* input=NULL;
    5541 
    5542         /*Find input: */
    5543         input=(Input*)this->inputs->GetInput(control_type);
    5544        
    5545         /*Do nothing if we  don't find it: */
    5546         if(!input)return;
    5547 
    5548         /*Constrain input using cm_min and cm_max: */
    5549         input->Constrain(cm_min,cm_max);
    5550 
    5551 }
    5552 /*}}}*/
    5553 /*FUNCTION Tria::GetVectorFromInputs(Vec vector,int NameEnum){{{1*/
    5554 void  Tria::GetVectorFromInputs(Vec vector,int NameEnum){
    5555 
    5556         int i;
    5557         const int numvertices=3;
    5558         int doflist1[numvertices];
    5559 
    5560         /*Find NameEnum input in the inputs dataset, and get it to fill in the vector: */
    5561         for(i=0;i<this->inputs->Size();i++){
    5562                 Input* input=(Input*)this->inputs->GetObjectByOffset(i);
    5563                 if(input->EnumType()==NameEnum){
    5564                         /*We found the enum.  Use its values to fill into the vector, using the vertices ids: */
    5565                         this->GetDofList1(&doflist1[0]);
    5566                         input->GetVectorFromInputs(vector,&doflist1[0]);
    5567                         break;
    5568                 }
    5569         }
    5570 }
    5571 /*}}}*/
    5572 /*FUNCTION Tria::InputConvergence(int* pconverged, double* eps, int* enums,int num_enums,int* criterionenums,double* criterionvalues,int num_criterionenums){{{1*/
    5573 void  Tria::InputConvergence(int* pconverged,double* eps, int* enums,int num_enums,int* criterionenums,double* criterionvalues,int num_criterionenums){
    5574 
    5575         int i;
    5576         Input** new_inputs=NULL;
    5577         Input** old_inputs=NULL;
    5578         int     converged=1;
    5579 
    5580         new_inputs=(Input**)xmalloc(num_enums/2*sizeof(Input*)); //half the enums are for the new inputs
    5581         old_inputs=(Input**)xmalloc(num_enums/2*sizeof(Input*)); //half the enums are for the old inputs
    5582        
    5583         for(i=0;i<num_enums/2;i++){
    5584                 new_inputs[i]=(Input*)this->inputs->GetInput(enums[2*i+0]);
    5585                 old_inputs[i]=(Input*)this->inputs->GetInput(enums[2*i+1]);
    5586                 if(!new_inputs[i])ISSMERROR("%s%s"," could not find input with enum ",EnumAsString(enums[2*i+0]));
    5587                 if(!old_inputs[i])ISSMERROR("%s%s"," could not find input with enum ",EnumAsString(enums[2*i+0]));
    5588         }
    5589 
    5590         /*ok, we've got the inputs (new and old), now loop throught the number of criterions and fill the eps array:*/
    5591         for(i=0;i<num_criterionenums;i++){
    5592                 IsInputConverged(eps+i,new_inputs,old_inputs,num_enums/2,criterionenums[i]);
    5593                 if(eps[i]>criterionvalues[i]) converged=0;
    5594         }
    5595 
    5596         /*Assign output pointers:*/
    5597         *pconverged=converged;
    5598 
    5599 }
    5600 /*}}}*/
     5353        double v13[3];
     5354        double v23[3];
     5355        double normal[3];
     5356        double normal_norm;
     5357
     5358        for (i=0;i<3;i++){
     5359                v13[i]=xyz_list[0][i]-xyz_list[2][i];
     5360                v23[i]=xyz_list[1][i]-xyz_list[2][i];
     5361        }
     5362
     5363        normal[0]=v13[1]*v23[2]-v13[2]*v23[1];
     5364        normal[1]=v13[2]*v23[0]-v13[0]*v23[2];
     5365        normal[2]=v13[0]*v23[1]-v13[1]*v23[0];
     5366
     5367        normal_norm=sqrt( pow(normal[0],(double)2)+pow(normal[1],(double)2)+pow(normal[2],(double)2) );
     5368
     5369        *(surface_normal)=normal[0]/normal_norm;
     5370        *(surface_normal+1)=normal[1]/normal_norm;
     5371        *(surface_normal+2)=normal[2]/normal_norm;
     5372
     5373}
     5374/*}}}*/
     5375/*FUNCTION Tria::UpdateFromDakota {{{1*/
     5376void  Tria::UpdateFromDakota(void* vinputs){
     5377
     5378        int     i;
     5379        int     dofs[1]={0};
     5380        double  temperature_list[3];
     5381        double  temperature_average;
     5382        double  B_list[3];
     5383        double  B_average;
     5384        double  new_h[3];
     5385
     5386        /*Update internal data if inputs holds new values: */
     5387        /*inputs->Recover("thickness",&this->properties.h[0],1,dofs,3,(void**)nodes);
     5388        if(inputs->Recover("thickness",&new_h[0],1,dofs,3,(void**)nodes)){
     5389        //density, needed later:
     5390        double di=(this->matpar->GetRhoIce()/this->matpar->GetRhoWater());
     5391        //Go through grids:
     5392        for (i=0;i<3;i++){
     5393        if(nodes[i]->IsOnShelf()){
     5394        this->b[i]=this->b[i]-di*(new_h[i]-h[i]); //hydrostatic equilibrium;
     5395        }
     5396        this->s[i]=this->b[i]+new_h[i];
     5397        this->h[i]=new_h[i];
     5398        }
     5399        }*/
     5400
     5401        ISSMERROR("not supported yet!");
     5402
     5403}
     5404/*}}}*/
  • issm/trunk/src/c/objects/Elements/Tria.h

    r4249 r4285  
    5454                /*Update virtual functions resolution: {{{1*/
    5555                void  InputUpdateFromSolution(double* solutiong);
    56                 void  InputUpdateFromSolutionDiagnosticHoriz( double* solution);
    57                 void  InputUpdateFromSolutionSlopeCompute( double* solution);
    58                 void  InputUpdateFromSolutionPrognostic( double* solution);
    59                 void  InputUpdateFromSolutionPrognostic2(double* solution);
    60                 void  InputUpdateFromSolutionBalancedthickness( double* solution);
    61                 void  InputUpdateFromSolutionBalancedthickness2( double* solution);
    62                 void  InputUpdateFromSolutionBalancedvelocities( double* solution);
    6356                void  InputUpdateFromVector(double* vector, int name, int type);
    6457                void  InputUpdateFromVector(int* vector, int name, int type);
     
    6760                void  InputUpdateFromConstant(int constant, int name);
    6861                void  InputUpdateFromConstant(bool constant, int name);
    69                 void  UpdateFromDakota(void* inputs);
    7062                /*}}}*/
    7163                /*Element virtual functions definitions: {{{1*/
     
    160152                void      GetSolutionFromInputsDiagnosticHoriz(Vec solution);
    161153                void      GradjDragStokes(Vec gradient);
     154                void      InputUpdateFromSolutionDiagnosticHoriz( double* solution);
     155                void      InputUpdateFromSolutionSlopeCompute( double* solution);
     156                void      InputUpdateFromSolutionPrognostic( double* solution);
     157                void      InputUpdateFromSolutionPrognostic2(double* solution);
     158                void      InputUpdateFromSolutionBalancedthickness( double* solution);
     159                void      InputUpdateFromSolutionBalancedthickness2( double* solution);
     160                void      InputUpdateFromSolutionBalancedvelocities( double* solution);
    162161                bool      IsInput(int name);
    163162                void      SetClone(int* minranks);
     
    165164                void*     SpawnSing(int g0);
    166165                void      SurfaceNormal(double* surface_normal, double xyz_list[3][3]);
     166                void      UpdateFromDakota(void* inputs);
    167167                /*}}}*/
    168168
  • issm/trunk/src/c/objects/Node.cpp

    r4248 r4285  
    151151                                analysis_type==PrognosticAnalysisEnum ||
    152152                                analysis_type==MeltingAnalysisEnum ||
    153                                 analysis_type==SlopeAnalysisEnum ||
     153                                analysis_type==BedSlopeAnalysisEnum ||
     154                                analysis_type==SurfaceSlopeAnalysisEnum ||
    154155                                analysis_type==BalancedvelocitiesAnalysisEnum ||
    155156                                analysis_type==BalancedthicknessAnalysisEnum
  • issm/trunk/src/c/shared/Dofs/DistributeNumDofs.cpp

    r4055 r4285  
    2525                numdofs=2;
    2626        }
    27         else if (analysis_type==SlopeAnalysisEnum){
     27        else if (analysis_type==BedSlopeAnalysisEnum || analysis_type==SurfaceSlopeAnalysisEnum){
    2828                numdofs=1;
    2929        }
  • issm/trunk/src/c/solutions/adjoint_core.cpp

    r4085 r4285  
    2020        char* solverstring=NULL;
    2121        bool  isstokes=false;
    22         bool conserve_loads=true;
     22        bool  conserve_loads=true;
     23        int   dim;
     24        int   solution_type;
    2325       
    2426        /*intermediary: */
     
    3739        femmodel->parameters->FindParam(&verbose,VerboseEnum);
    3840        femmodel->parameters->FindParam(&isstokes,IsStokesEnum);
     41        femmodel->parameters->FindParam(&dim,DimEnum);
     42        femmodel->parameters->FindParam(&solution_type,SolutionTypeEnum);
    3943
    4044        /*set analysis type to compute velocity: */
     
    7276        InputUpdateFromSolutionx( femmodel->elements,femmodel->nodes, femmodel->vertices, femmodel->loads, femmodel->materials, femmodel->parameters,adjoint_g);
    7377
     78        if(verbose)_printf_("saving results:\n");
     79        if(solution_type==AdjointAnalysisEnum){
     80                InputToResultx(femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,AdjointxEnum);
     81                InputToResultx(femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,AdjointyEnum);
     82                if(dim==3) InputToResultx(femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,AdjointzEnum);
     83        }
     84       
    7485        /*Free ressources:*/
    7586        xfree((void**)&solverstring);
  • issm/trunk/src/c/solutions/balancedthickness2_core.cpp

    r4073 r4285  
    1717        int verbose=0;
    1818        int dim;
     19        int solution_type;
    1920
    2021        /*activate formulation: */
     
    2425        femmodel->parameters->FindParam(&verbose,VerboseEnum);
    2526        femmodel->parameters->FindParam(&dim,DimEnum);
     27        femmodel->parameters->FindParam(&solution_type,SolutionTypeEnum);
    2628
    2729        _printf_("depth averaging velocity...\n");
     
    4244
    4345        if(verbose)_printf_("saving results:\n");
    44         InputToResultx(femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,ThicknessEnum);
     46        if(solution_type==Balancedthickness2AnalysisEnum){
     47                InputToResultx(femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,ThicknessEnum);
     48        }
     49
    4550
    4651}
  • issm/trunk/src/c/solutions/balancedthickness_core.cpp

    r4073 r4285  
    1717        int verbose=0;
    1818        int dim;
     19        int solution_type;
    1920
    2021        /*activate formulation: */
     
    2425        femmodel->parameters->FindParam(&verbose,VerboseEnum);
    2526        femmodel->parameters->FindParam(&dim,DimEnum);
     27        femmodel->parameters->FindParam(&solution_type,SolutionTypeEnum);
    2628
    2729        _printf_("depth averaging velocity...\n");
     
    3739
    3840        if(verbose)_printf_("saving results:\n");
    39         InputToResultx(femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,ThicknessEnum);
     41        if(solution_type==BalancedthicknessAnalysisEnum){
     42                InputToResultx(femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,ThicknessEnum);
     43        }
    4044
    4145}
  • issm/trunk/src/c/solutions/balancedvelocities_core.cpp

    r4073 r4285  
    1616        int verbose=0;
    1717        int dim;
     18        int solution_type;
    1819
    1920        /*activate formulation: */
     
    2324        femmodel->parameters->FindParam(&verbose,VerboseEnum);
    2425        femmodel->parameters->FindParam(&dim,DimEnum);
     26        femmodel->parameters->FindParam(&solution_type,SolutionTypeEnum);
    2527
    2628        _printf_("depth averaging velocity...\n");
     
    3739
    3840        if(verbose)_printf_("saving results:\n");
    39         InputToResultx(femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,VxEnum);
    40         InputToResultx(femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,VyEnum);
     41        if(solution_type==BalancedvelocitiesAnalysisEnum){
     42                InputToResultx(femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,VxEnum);
     43                InputToResultx(femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,VyEnum);
     44        }
    4145
    4246}
  • issm/trunk/src/c/solutions/bedslope.cpp

    r4236 r4285  
    3737        double   start_init, finish_init;
    3838
    39         int analyses[1]={SlopeAnalysisEnum};
    40         int solution_type=SlopeAnalysisEnum;
     39        int analyses[1]={BedSlopeAnalysisEnum};
     40        int solution_type=BedSlopeAnalysisEnum;
    4141
    4242        MODULEBOOT();
  • issm/trunk/src/c/solutions/bedslope_core.cpp

    r4064 r4285  
    1313
    1414        /*parameters: */
    15         int verbose;
    16         int dim;
     15        int  verbose;
     16        int  dim;
    1717        bool isstokes;
    1818        bool ishutter;
     19        int  solution_type;
    1920
    2021        /*Recover some parameters: */
    2122        femmodel->parameters->FindParam(&verbose,VerboseEnum);
    2223        femmodel->parameters->FindParam(&dim,DimEnum);
     24        femmodel->parameters->FindParam(&solution_type,SolutionTypeEnum);
    2325
    2426        if(verbose)_printf_("%s\n","computing slope...");
     
    3840       
    3941        if(verbose)_printf_("saving results:\n");
    40         InputToResultx(femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,BedSlopeXEnum);
    41         InputToResultx(femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,BedSlopeYEnum);
     42        if(solution_type==BedSlopeAnalysisEnum){
     43                InputToResultx(femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,BedSlopeXEnum);
     44                InputToResultx(femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,BedSlopeYEnum);
     45        }
    4246
    4347}
  • issm/trunk/src/c/solutions/control_core.cpp

    r4079 r4285  
    2626        double  cm_max;
    2727        int     cm_gradient;
     28        int     dim;
    2829
    2930        double* fit=NULL;
     
    5758        femmodel->parameters->FindParam(&cm_gradient,CmGradientEnum);
    5859        femmodel->parameters->FindParam(&control_steady,ControlSteadyEnum);
     60        femmodel->parameters->FindParam(&dim,DimEnum);
    5961        /*}}}*/
    6062
     
    116118        /*some results not computed by steadystate_core or diagnostic_core: */
    117119        InputToResultx(femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,control_type); //the parameter itself!
     120        InputToResultx(femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,VxEnum);
     121        InputToResultx(femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,VyEnum);
     122        InputToResultx(femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,VelEnum);
     123        InputToResultx(femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,GradientEnum);
     124        InputToResultx(femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,AdjointxEnum);
     125        InputToResultx(femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,AdjointyEnum);
     126        if(dim==3)InputToResultx(femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,VzEnum);
    118127        femmodel->results->AddObject(new DoubleVecExternalResult(femmodel->results->Size()+1,JEnum,J,nsteps,1,0));
    119128        femmodel->results->AddObject(new StringExternalResult(femmodel->results->Size()+1,ControlTypeEnum,EnumAsString(control_type),1,0));
  • issm/trunk/src/c/solutions/diagnostic_core.cpp

    r4253 r4285  
    2424        bool conserve_loads=true;
    2525        bool modify_loads=true;
     26        int solution_type;
    2627
    2728        /* recover parameters:*/
     
    3334        femmodel->parameters->FindParam(&stokesreconditioning,StokesReconditioningEnum);
    3435        femmodel->parameters->FindParam(&qmu_analysis,QmuAnalysisEnum);
     36        femmodel->parameters->FindParam(&solution_type,SolutionTypeEnum);
    3537
    3638        /*for qmu analysis, reinitialize velocity so that fake sensitivities do not show up as a result of a different restart of the convergence at each trial.*/
     
    8587
    8688        if(verbose)_printf_("saving results:\n");
    87         InputToResultx(femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,VxEnum);
    88         InputToResultx(femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,VyEnum);
    89         InputToResultx(femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,VelEnum);
    90         InputToResultx(femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,PressureEnum);
    91         if(dim==3) InputToResultx(femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,VzEnum);
    92 
     89        if(solution_type==DiagnosticAnalysisEnum){
     90                InputToResultx(femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,VxEnum);
     91                InputToResultx(femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,VyEnum);
     92                InputToResultx(femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,VelEnum);
     93                InputToResultx(femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,PressureEnum);
     94                if(dim==3) InputToResultx(femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,VzEnum);
     95        }
    9396}
  • issm/trunk/src/c/solutions/prognostic2_core.cpp

    r4055 r4285  
    1515        /*flags: */
    1616        int verbose=0;
     17        int solution_type;
    1718
    1819        /*activate formulation: */
     
    2122        /*recover parameters: */
    2223        femmodel->parameters->FindParam(&verbose,VerboseEnum);
     24        femmodel->parameters->FindParam(&solution_type,SolutionTypeEnum);
    2325
    2426        _printf_("depth averaging velocity...\n");
     
    3537
    3638        if(verbose)_printf_("saving results:\n");
    37         InputToResultx(femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,ThicknessEnum);
     39        if(solution_type==Prognostic2AnalysisEnum){
     40                InputToResultx(femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,ThicknessEnum);
     41        }
    3842
    3943}
  • issm/trunk/src/c/solutions/prognostic_core.cpp

    r4073 r4285  
    1515        /*parameters: */
    1616        int verbose=0;
     17        int solution_type;
    1718
    1819        /*activate formulation: */
     
    2122        /*recover parameters: */
    2223        femmodel->parameters->FindParam(&verbose,VerboseEnum);
     24        femmodel->parameters->FindParam(&solution_type,SolutionTypeEnum);
    2325
    2426        _printf_("depth averaging velocity...\n");
     
    3335
    3436        if(verbose)_printf_("saving results:\n");
    35         InputToResultx(femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,ThicknessEnum);
     37        if(solution_type==PrognosticAnalysisEnum){
     38                InputToResultx(femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,ThicknessEnum);
     39        }
    3640       
    3741}
  • issm/trunk/src/c/solutions/steadystate_core.cpp

    r4125 r4285  
    2020        int verbose;
    2121        int dim;
     22        int solution_type;
    2223       
    2324        /* recover parameters:*/
    2425        femmodel->parameters->FindParam(&verbose,VerboseEnum);
    2526        femmodel->parameters->FindParam(&dim,DimEnum);
     27        femmodel->parameters->FindParam(&solution_type,SolutionTypeEnum);
    2628
    2729        /*intialize counters: */
     
    5658       
    5759        if(verbose)_printf_("saving results:\n");
    58         InputToResultx(femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,VxEnum);
    59         InputToResultx(femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,VyEnum);
    60         InputToResultx(femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,PressureEnum);
    61         if(dim==3) InputToResultx(femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,VzEnum);
    62         InputToResultx(femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,TemperatureEnum);
     60        if(solution_type==SteadystateAnalysisEnum){
     61                InputToResultx(femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,VxEnum);
     62                InputToResultx(femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,VyEnum);
     63                InputToResultx(femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,PressureEnum);
     64                if(dim==3) InputToResultx(femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,VzEnum);
     65                InputToResultx(femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,TemperatureEnum);
     66        }
    6367}
  • issm/trunk/src/c/solutions/surfaceslope.cpp

    r4236 r4285  
    3737        double   start_init, finish_init;
    3838
    39         int analyses[1]={SlopeAnalysisEnum};
    40         int solution_type=SlopeAnalysisEnum;
     39        int analyses[1]={SurfaceSlopeAnalysisEnum};
     40        int solution_type=SurfaceSlopeAnalysisEnum;
    4141
    4242        MODULEBOOT();
  • issm/trunk/src/c/solutions/surfaceslope_core.cpp

    r4064 r4285  
    1717        bool isstokes;
    1818        bool ishutter;
     19        int solution_type;
    1920
    2021        /*Recover some parameters: */
    2122        femmodel->parameters->FindParam(&verbose,VerboseEnum);
    2223        femmodel->parameters->FindParam(&dim,DimEnum);
     24        femmodel->parameters->FindParam(&solution_type,SolutionTypeEnum);
    2325
    2426        if(verbose)_printf_("%s\n","computing slope...");
     
    3840       
    3941        if(verbose)_printf_("saving results:\n");
    40         InputToResultx(femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,SurfaceSlopeXEnum);
    41         InputToResultx(femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,SurfaceSlopeYEnum);
     42        if(solution_type==SurfaceSlopeAnalysisEnum){
     43                InputToResultx(femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,SurfaceSlopeXEnum);
     44                InputToResultx(femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,SurfaceSlopeYEnum);
     45        }
    4246
    4347}
  • issm/trunk/src/c/solutions/thermal_core.cpp

    r4055 r4285  
    2323        double dt;
    2424        double melting_offset;
     25        int solution_type;
    2526
    2627        //first recover parameters common to all solutions
     
    2829        femmodel->parameters->FindParam(&ndt,NdtEnum);
    2930        femmodel->parameters->FindParam(&dt,DtEnum);
     31        femmodel->parameters->FindParam(&solution_type,SolutionTypeEnum);
    3032
    3133        /*Compute number of time steps: */
     
    4648
    4749                if(verbose)_printf_("saving results:\n");
    48                 InputToResultx(femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,TemperatureEnum,i,time);
    49                 InputToResultx(femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,MeltingRateEnum,i,time);
     50                if(solution_type==ThermalAnalysisEnum){
     51                        InputToResultx(femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,TemperatureEnum,i,time);
     52                        InputToResultx(femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,MeltingRateEnum,i,time);
     53                }
    5054
    5155        }
  • issm/trunk/src/c/solutions/transient2d_core.cpp

    r4055 r4285  
    1818        double finaltime;
    1919        double dt;
     20        int solution_type;
    2021       
    2122        /*intermediary: */
     
    2728        femmodel->parameters->FindParam(&finaltime,NdtEnum);
    2829        femmodel->parameters->FindParam(&dt,DtEnum);
     30        femmodel->parameters->FindParam(&solution_type,SolutionTypeEnum);
    2931
    3032        /*initialize: */
     
    3638                _printf_("%s%g%s%i%s%g\n","time [yr]: ",time,"    iteration number: ",step,"/",floor(finaltime/dt));
    3739
     40                /*Set step and time: */
     41                time+=dt;
    3842                step+=1;
    39                 time+=dt;
    4043
    4144                if(verbose)_printf_("%s\n","computing new velocity");
     
    4952
    5053                if(verbose)_printf_("%s\n","saving results:\n");
    51                 InputToResultx(femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,VxEnum,step,time);
    52                 InputToResultx(femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,VyEnum,step,time);
    53                 InputToResultx(femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,PressureEnum,step,time);
    54                 InputToResultx(femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,ThicknessEnum,step,time);
    55                 InputToResultx(femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,SurfaceEnum,step,time);
    56                 InputToResultx(femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,BedEnum,step,time);
     54                if(solution_type==Transient2DAnalysisEnum){
     55                        InputToResultx(femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,VxEnum,step,time);
     56                        InputToResultx(femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,VyEnum,step,time);
     57                        InputToResultx(femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,VelEnum,step,time);
     58                        InputToResultx(femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,PressureEnum,step,time);
     59                        InputToResultx(femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,ThicknessEnum,step,time);
     60                        InputToResultx(femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,SurfaceEnum,step,time);
     61                        InputToResultx(femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,BedEnum,step,time);
     62                }
    5763        }
    5864
  • issm/trunk/src/c/solutions/transient3d_core.cpp

    r4211 r4285  
    1818        double finaltime;
    1919        double dt;
     20        int solution_type;
    2021       
    2122        /*intermediary: */
     
    2728        femmodel->parameters->FindParam(&finaltime,NdtEnum);
    2829        femmodel->parameters->FindParam(&dt,DtEnum);
     30        femmodel->parameters->FindParam(&solution_type,SolutionTypeEnum);
    2931
    3032        /*initialize: */
     
    5860
    5961                if(verbose)_printf_("%s\n","saving results:\n");
    60                 InputToResultx(femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,VxEnum,step,time);
    61                 InputToResultx(femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,VyEnum,step,time);
    62                 InputToResultx(femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,VzEnum,step,time);
    63                 InputToResultx(femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,PressureEnum,step,time);
    64                 InputToResultx(femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,ThicknessEnum,step,time);
    65                 InputToResultx(femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,SurfaceEnum,step,time);
    66                 InputToResultx(femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,BedEnum,step,time);
    67                 InputToResultx(femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,TemperatureEnum,step,time);
    68                 InputToResultx(femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,MeltingRateEnum,step,time);
     62                if(solution_type==Transient3DAnalysisEnum){
     63                        InputToResultx(femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,VxEnum,step,time);
     64                        InputToResultx(femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,VyEnum,step,time);
     65                        InputToResultx(femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,VzEnum,step,time);
     66                        InputToResultx(femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,PressureEnum,step,time);
     67                        InputToResultx(femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,ThicknessEnum,step,time);
     68                        InputToResultx(femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,SurfaceEnum,step,time);
     69                        InputToResultx(femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,BedEnum,step,time);
     70                        InputToResultx(femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,TemperatureEnum,step,time);
     71                        InputToResultx(femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,MeltingRateEnum,step,time);
     72                }
    6973
    7074                if (step%5==0){
Note: See TracChangeset for help on using the changeset viewer.