Changeset 9775


Ignore:
Timestamp:
09/12/11 12:42:33 (14 years ago)
Author:
Eric.Larour
Message:

Reduced compilation to the maximum when adic flag is on, so that we do not have to forward differentiate the whole code.
Added 3D, Rifts, Transient, Prognostic, Steadystate conditional compilation.
Added eraselinks in src/ad/ directory to get rid of symlinks.
From mods in ad/Makefile.am, applied to c/Makefile.am -> better compilation.

Location:
issm/trunk/src
Files:
23 edited

Legend:

Unmodified
Added
Removed
  • issm/trunk/src/ad/eraselinks.sh

    r9773 r9775  
    77rm shared
    88rm toolkits
    9 rm iorm EnumDefinitions
     9rm io
     10rm EnumDefinitions
    1011rm modules
    1112rm solutions
  • issm/trunk/src/c/Container/DataSet.cpp

    r9761 r9775  
    229229                                dataset->AddObject(triavertexinput);}
    230230                                break;
     231                        #ifdef _HAVE_THREED_
    231232                        case PentaVertexInputEnum:{
    232233                                PentaVertexInput* pentavertexinput=NULL;
     
    235236                                dataset->AddObject(pentavertexinput);}
    236237                                break;
     238                        #endif
    237239                        case TransientInputEnum:{
    238240                                TransientInput* transientinput=NULL;
     
    261263                                dataset->AddObject(triavertexelementresult);}
    262264                                break;
     265                         #ifdef _HAVE_THREED_
    263266                        case PentaVertexElementResultEnum:{
    264267                                PentaVertexElementResult* pentavertexelementresult=NULL;
     
    273276                                dataset->AddObject(penta);}
    274277                                break;
     278                        #endif
    275279                        case MaticeEnum:{
    276280                                Matice* matice=NULL;
     
    327331                                dataset->AddObject(numericalflux);}
    328332                                break;
     333                        #ifdef _HAVE_RIFTS_
    329334                        case RiftfrontEnum:{
    330335                                Riftfront* riftfront=NULL;
     
    333338                                dataset->AddObject(riftfront);}
    334339                                break;
     340                        #endif
    335341                        case DoubleInputEnum:{
    336342                                DoubleInput* doubleinput=NULL;
  • issm/trunk/src/c/Container/Loads.cpp

    r9320 r9775  
    7878}
    7979/*}}}*/
    80 /*FUNCTION Loads::OutputRifts{{{1*/
    81 void  Loads::OutputRifts(Vec riftproperties){
    82 
    83         int i;
    84 
    85         for(i=0;i<this->Size();i++){
    86 
    87                 Object* object=(Object*)this->GetObjectByOffset(i);
    88 
    89                 if(object->Enum()==RiftfrontEnum){
    90 
    91                         Riftfront* riftfront=(Riftfront*)object;
    92                         riftfront->OutputProperties(riftproperties);
    93                 }
    94         }
    95 }
    96 /*}}}*/
    9780/*FUNCTION Loads::SetCurrentConfiguration{{{1*/
    9881void Loads::SetCurrentConfiguration(Elements* elements,Loads* loads, Nodes* nodes, Vertices* vertices, Materials* materials,Parameters* parameters){
  • issm/trunk/src/c/Container/Loads.h

    r6411 r9775  
    2828                void  Configure(Elements* elements,Loads* loads, Nodes* nodes, Vertices* vertices, Materials* materials,Parameters* parameters);
    2929                int   NumberOfLoads(void);
    30                 void  OutputRifts(Vec riftproperties);
    3130                void  SetCurrentConfiguration(Elements* elements,Loads* loads, Nodes* nodes, Vertices* vertices, Materials* materials,Parameters* parameters);
    3231                /*}}}*/
  • issm/trunk/src/c/Makefile.am

    r9761 r9775  
    11INCLUDES = @DAKOTAINCL@ @PETSCINCL@ @SLEPCINCL@ @MPIINCL@ @MATLABINCL@  @METISINCL@  @CHACOINCL@ @SCOTCHINCL@ @PLAPACKINCL@  @BLASLAPACKINCL@ @MKLINCL@ @MUMPSINCL@  @TRIANGLEINCL@ @HYPREINCL@ @MLINCL@ @TAOINCL@
    22
     3#Library declaration {{{1
    34#Compile serial library, and then try and compile parallel library
    45if NOSERIAL
     
    1617endif
    1718
    18 #Overload library, to overload any non-standard symbols.
    19 libOverload_a_SOURCES = ./shared/String/stricmp.c
    20 libOverload_a_CFLAGS = -fPIC -D_PARALLEL_   -D_C_ $(COPTFLAGS)
    21 
    22 #Serial compilation
     19#}}}
     20
     21#For serial compilation
     22#ISSM serial library{{{1
    2323libISSM_a_SOURCES = ./include/macros.h\
    2424                                        ./include/typedefs.h\
     
    689689                                        ./modules/InputConvergencex/InputConvergencex.cpp\
    690690                                        ./modules/InputConvergencex/InputConvergencex.h\
    691                                         ./modules/OutputRiftsx/OutputRiftsx.h\
    692                                         ./modules/OutputRiftsx/OutputRiftsx.cpp\
    693691                                        ./modules/Bamgx/Bamgx.cpp\
    694692                                        ./modules/Bamgx/Bamgx.h\
     
    712710endif
    713711
    714 #Parallel compilation
     712#}}}
     713
     714#For parallel compilation
     715#ISSM parallel library  {{{1
    715716libpISSM_a_SOURCES = ./include/macros.h\
    716717                                        ./include/typedefs.h\
    717718                                        ./include/types.h\
    718                                         ./include/globals.h\
    719719                                        ./include/include.h\
    720720                                        ./objects/objects.h\
    721721                                        ./objects/Object.h\
    722                                         ./objects/Bamg/BamgGeom.h\
    723                                         ./objects/Bamg/BamgGeom.cpp\
    724                                         ./objects/Bamg/BamgMesh.h\
    725                                         ./objects/Bamg/BamgMesh.cpp\
    726                                         ./objects/Bamg/BamgOpts.h\
    727                                         ./objects/Bamg/BamgOpts.cpp\
    728                                         ./objects/Bamg/BamgObjects.h \
    729                                         ./objects/Bamg/CrackedEdge.h\
    730                                         ./objects/Bamg/CrackedEdge.cpp\
    731                                         ./objects/Bamg/Curve.h\
    732                                         ./objects/Bamg/Curve.cpp\
    733                                         ./objects/Bamg/Direction.h\
    734                                         ./objects/Bamg/Direction.cpp\
    735                                         ./objects/Bamg/DoubleAndInt.h\
    736                                         ./objects/Bamg/Edge.h\
    737                                         ./objects/Bamg/Edge.cpp\
    738                                         ./objects/Bamg/GeomEdge.h\
    739                                         ./objects/Bamg/GeomEdge.cpp\
    740                                         ./objects/Bamg/GeomSubDomain.h\
    741                                         ./objects/Bamg/GeomSubDomain.cpp\
    742                                         ./objects/Bamg/GeomVertex.h\
    743                                         ./objects/Bamg/GeomVertex.cpp\
    744                                         ./objects/Bamg/Geometry.h\
    745                                         ./objects/Bamg/Geometry.cpp\
    746                                         ./objects/Bamg/ListofIntersectionTriangles.cpp\
    747                                         ./objects/Bamg/ListofIntersectionTriangles.h\
    748                                         ./objects/Bamg/EigenMetric.cpp\
    749                                         ./objects/Bamg/Metric.cpp\
    750                                         ./objects/Bamg/Metric.h\
    751                                         ./objects/Bamg/QuadTree.cpp\
    752                                         ./objects/Bamg/QuadTree.h\
    753                                         ./objects/Bamg/R2.h\
    754                                         ./objects/Bamg/SetOfE4.cpp\
    755                                         ./objects/Bamg/SetOfE4.h\
    756                                         ./objects/Bamg/SubDomain.h\
    757                                         ./objects/Bamg/SubDomain.cpp\
    758                                         ./objects/Bamg/AdjacentTriangle.h\
    759                                         ./objects/Bamg/AdjacentTriangle.cpp\
    760                                         ./objects/Bamg/Triangle.cpp\
    761                                         ./objects/Bamg/Triangle.h\
    762                                         ./objects/Bamg/BamgVertex.cpp\
    763                                         ./objects/Bamg/BamgVertex.h\
    764                                         ./objects/Bamg/VertexOnEdge.h\
    765                                         ./objects/Bamg/VertexOnEdge.cpp\
    766                                         ./objects/Bamg/VertexOnGeom.h\
    767                                         ./objects/Bamg/VertexOnGeom.cpp\
    768                                         ./objects/Bamg/VertexOnVertex.h\
    769                                         ./objects/Bamg/VertexOnVertex.cpp\
    770                                         ./objects/Bamg/Mesh.h\
    771                                         ./objects/Bamg/Mesh.cpp\
    772722                                        ./objects/Gauss/GaussTria.h\
    773723                                        ./objects/Gauss/GaussTria.cpp\
    774                                         ./objects/Gauss/GaussPenta.h\
    775                                         ./objects/Gauss/GaussPenta.cpp\
    776                                         ./objects/KML/KML_Attribute.cpp\
    777                                         ./objects/KML/KML_Attribute.h\
    778                                         ./objects/KML/KML_ColorStyle.cpp\
    779                                         ./objects/KML/KML_ColorStyle.h\
    780                                         ./objects/KML/KML_Container.cpp\
    781                                         ./objects/KML/KML_Container.h\
    782                                         ./objects/KML/KML_Document.cpp\
    783                                         ./objects/KML/KML_Document.h\
    784                                         ./objects/KML/KML_Feature.cpp\
    785                                         ./objects/KML/KML_Feature.h\
    786                                         ./objects/KML/KML_File.cpp\
    787                                         ./objects/KML/KML_File.h\
    788                                         ./objects/KML/KML_Folder.cpp\
    789                                         ./objects/KML/KML_Folder.h\
    790                                         ./objects/KML/KML_Geometry.cpp\
    791                                         ./objects/KML/KML_Geometry.h\
    792                                         ./objects/KML/KML_GroundOverlay.cpp\
    793                                         ./objects/KML/KML_GroundOverlay.h\
    794                                         ./objects/KML/KML_Icon.cpp\
    795                                         ./objects/KML/KML_Icon.h\
    796                                         ./objects/KML/KML_LatLonBox.cpp\
    797                                         ./objects/KML/KML_LatLonBox.h\
    798                                         ./objects/KML/KML_LinearRing.cpp\
    799                                         ./objects/KML/KML_LinearRing.h\
    800                                         ./objects/KML/KML_LineString.cpp\
    801                                         ./objects/KML/KML_LineString.h\
    802                                         ./objects/KML/KML_LineStyle.cpp\
    803                                         ./objects/KML/KML_LineStyle.h\
    804                                         ./objects/KML/KML_MultiGeometry.cpp\
    805                                         ./objects/KML/KML_MultiGeometry.h\
    806                                         ./objects/KML/KML_Object.cpp\
    807                                         ./objects/KML/KML_Object.h\
    808                                         ./objects/KML/KML_Overlay.cpp\
    809                                         ./objects/KML/KML_Overlay.h\
    810                                         ./objects/KML/KML_Placemark.cpp\
    811                                         ./objects/KML/KML_Placemark.h\
    812                                         ./objects/KML/KML_Polygon.cpp\
    813                                         ./objects/KML/KML_Polygon.h\
    814                                         ./objects/KML/KML_PolyStyle.cpp\
    815                                         ./objects/KML/KML_PolyStyle.h\
    816                                         ./objects/KML/KML_Style.cpp\
    817                                         ./objects/KML/KML_Style.h\
    818                                         ./objects/KML/KML_StyleSelector.cpp\
    819                                         ./objects/KML/KML_StyleSelector.h\
    820                                         ./objects/KML/KML_SubStyle.cpp\
    821                                         ./objects/KML/KML_SubStyle.h\
    822                                         ./objects/KML/KMLFileReadUtils.cpp\
    823                                         ./objects/KML/KMLFileReadUtils.h\
    824                                         ./objects/Options/Option.cpp\
    825                                         ./objects/Options/Option.h\
    826                                         ./objects/Options/OptionDouble.cpp\
    827                                         ./objects/Options/OptionDouble.h\
    828                                         ./objects/Options/OptionLogical.cpp\
    829                                         ./objects/Options/OptionLogical.h\
    830                                         ./objects/Options/OptionChar.cpp\
    831                                         ./objects/Options/OptionChar.h\
    832                                         ./objects/Options/OptionStruct.cpp\
    833                                         ./objects/Options/OptionStruct.h\
    834                                         ./objects/Options/OptionCell.cpp\
    835                                         ./objects/Options/OptionCell.h\
    836                                         ./objects/Options/OptionUtilities.cpp\
    837                                         ./objects/Options/OptionUtilities.h\
    838724                                        ./objects/Update.h\
    839725                                        ./objects/Element.h\
     
    848734                                        ./objects/Loads/Friction.h\
    849735                                        ./objects/Loads/Friction.cpp\
    850                                         ./objects/DakotaPlugin.h\
    851                                         ./objects/DakotaPlugin.cpp\
     736                                        ./objects/Inputs/TransientInput.h\
     737                                        ./objects/Inputs/TransientInput.cpp\
     738                                        ./objects/Constraints/SpcTransient.cpp\
     739                                        ./objects/Constraints/SpcTransient.h\
    852740                                        ./objects/DofIndexing.h\
    853741                                        ./objects/DofIndexing.cpp\
     
    869757                                        ./objects/ElementResults/TriaVertexElementResult.h\
    870758                                        ./objects/ElementResults/TriaVertexElementResult.cpp\
    871                                         ./objects/ElementResults/PentaVertexElementResult.h\
    872                                         ./objects/ElementResults/PentaVertexElementResult.cpp\
    873759                                        ./objects/ElementResults/BoolElementResult.h\
    874760                                        ./objects/ElementResults/BoolElementResult.cpp\
     
    898784                                        ./objects/Inputs/TriaVertexInput.h\
    899785                                        ./objects/Inputs/TriaVertexInput.cpp\
    900                                         ./objects/Inputs/PentaVertexInput.h\
    901                                         ./objects/Inputs/PentaVertexInput.cpp\
    902786                                        ./objects/Inputs/BoolInput.h\
    903787                                        ./objects/Inputs/BoolInput.cpp\
     
    906790                                        ./objects/Inputs/DoubleInput.h\
    907791                                        ./objects/Inputs/DoubleInput.cpp\
    908                                         ./objects/Inputs/ControlInput.h\
    909                                         ./objects/Inputs/ControlInput.cpp\
    910792                                        ./objects/Inputs/DatasetInput.h\
    911793                                        ./objects/Inputs/DatasetInput.cpp\
    912                                         ./objects/Inputs/TransientInput.h\
    913                                         ./objects/Inputs/TransientInput.cpp\
    914                                         ./objects/Elements/Penta.h\
    915                                         ./objects/Elements/Penta.cpp\
    916                                         ./objects/Elements/PentaHook.h\
    917                                         ./objects/Elements/PentaHook.cpp\
    918                                         ./objects/Elements/PentaRef.h\
    919                                         ./objects/Elements/PentaRef.cpp\
    920794                                        ./objects/Materials/Matice.h\
    921795                                        ./objects/Materials/Matice.cpp\
     
    927801                                        ./objects/Constraints/SpcDynamic.cpp\
    928802                                        ./objects/Constraints/SpcDynamic.h\
    929                                         ./objects/Constraints/SpcTransient.cpp\
    930                                         ./objects/Constraints/SpcTransient.h\
    931803                                        ./objects/Loads/Penpair.cpp\
    932804                                        ./objects/Loads/Penpair.h\
     
    935807                                        ./objects/Loads/Icefront.cpp\
    936808                                        ./objects/Loads/Icefront.h\
    937                                         ./objects/Loads/Riftfront.cpp\
    938                                         ./objects/Loads/Riftfront.h\
    939809                                        ./objects/Loads/Numericalflux.cpp\
    940810                                        ./objects/Loads/Numericalflux.h\
     
    994864                                        ./Container/Vertices.cpp\
    995865                                        ./shared/shared.h\
    996                                         ./shared/Threads/issm_threads.h\
    997                                         ./shared/Threads/LaunchThread.cpp\
    998                                         ./shared/Threads/PartitionRange.cpp\
    999866                                        ./shared/Alloc/alloc.h\
    1000867                                        ./shared/Alloc/alloc.cpp\
    1001                                         ./shared/Matlab/matlabshared.h\
    1002                                         ./shared/Matlab/ModuleBoot.cpp\
    1003                                         ./shared/Matlab/mxGetAssignedField.cpp\
    1004                                         ./shared/Matlab/mxGetField.cpp\
    1005                                         ./shared/Matlab/CheckNumMatlabArguments.cpp\
    1006868                                        ./shared/Matrix/matrix.h\
    1007869                                        ./shared/Matrix/MatrixUtils.cpp\
     
    1016878                                        ./shared/Numerics/cross.cpp\
    1017879                                        ./shared/Numerics/norm.cpp\
    1018                                         ./shared/Numerics/BrentSearch.cpp\
    1019                                         ./shared/Numerics/OptimalSearch.cpp\
    1020                                         ./shared/Numerics/OptFunc.cpp\
    1021880                                        ./shared/Numerics/extrema.cpp\
    1022881                                        ./shared/Numerics/UnitConversion.cpp\
     
    1025884                                        ./shared/Exceptions/Exceptions.cpp\
    1026885                                        ./shared/Exceptions/exprintf.cpp\
    1027                                         ./shared/Exp/exp.h\
    1028                                         ./shared/Exp/IsInPoly.cpp\
    1029                                         ./shared/Exp/IsInPolySerial.cpp\
    1030                                         ./shared/Exp/DomainOutlineRead.cpp\
    1031                                         ./shared/Exp/DomainOutlineWrite.cpp\
    1032                                         ./shared/TriMesh/trimesh.h\
    1033                                         ./shared/TriMesh/AssociateSegmentToElement.cpp\
    1034                                         ./shared/TriMesh/GridInsideHole.cpp\
    1035                                         ./shared/TriMesh/OrderSegments.cpp\
    1036                                         ./shared/TriMesh/SplitMeshForRifts.cpp\
    1037                                         ./shared/TriMesh/TriMeshUtils.cpp\
    1038886                                        ./shared/Sorting/binary_search.cpp\
    1039887                                        ./shared/Sorting/sorting.h\
     
    1046894                                        ./shared/Elements/GetNumberOfDofs.cpp\
    1047895                                        ./shared/String/sharedstring.h\
    1048                                         ./shared/Bamg/Abs.h \
    1049                                         ./shared/Bamg/BigPrimeNumber.h\
    1050                                         ./shared/Bamg/BigPrimeNumber.cpp\
    1051                                         ./shared/Bamg/BinaryRand.h \
    1052                                         ./shared/Bamg/det.h \
    1053                                         ./shared/Bamg/Exchange.h \
    1054                                         ./shared/Bamg/extrema.h \
    1055                                         ./shared/Bamg/HeapSort.h \
    1056                                         ./shared/Bamg/OppositeAngle.h \
    1057896                                        ./toolkits/petsc\
    1058897                                        ./toolkits/petsc/patches\
     
    1098937                                        ./io/Disk/pfopen.cpp\
    1099938                                        ./io/Disk/pfclose.cpp\
    1100                                         ./io/Matlab/matlabio.h\
    1101                                         ./io/Matlab/WriteMatlabData.cpp\
    1102                                         ./io/Matlab/FetchMatlabData.cpp\
    1103                                         ./io/Matlab/OptionParse.cpp\
    1104939                                        ./io/PrintfFunction.cpp\
    1105940                                        ./EnumDefinitions/EnumDefinitions.h\
    1106941                                        ./EnumDefinitions/EnumToModelField.cpp\
    1107                                         ./modules/AddExternalResultx/AddExternalResultx.h\
    1108                                         ./modules/AddExternalResultx/AddExternalResultx.cpp\
    1109                                         ./modules/Chacox/Chacox.h\
    1110                                         ./modules/Chacox/Chacox.cpp\
    1111                                         ./modules/Chacox/input_parse.cpp\
    1112                                         ./modules/Chacox/chaco_seconds.cpp\
    1113                                         ./modules/Chacox/user_params.cpp\
    1114                                         ./modules/GroundingLineMigrationx/GroundingLineMigrationx.cpp\
    1115                                         ./modules/GroundingLineMigrationx/GroundingLineMigrationx.h\
    1116                                         ./modules/GroundingLineMigrationx/GroundingLineMigrationxLocal.h\
    1117                                         ./modules/GroundingLineMigrationx/GroundingLineMigrationxUtils.cpp\
    1118942                                        ./modules/ModelProcessorx/ModelProcessorx.h\
    1119943                                        ./modules/ModelProcessorx/ModelProcessorx.cpp\
     
    1128952                                        ./modules/ModelProcessorx/CreateNumberNodeToElementConnectivity.cpp\
    1129953                                        ./modules/ModelProcessorx/CreateElementsVerticesAndMaterials.cpp\
    1130                                         ./modules/ModelProcessorx/DiagnosticHoriz/UpdateElementsDiagnosticHoriz.cpp\
    1131                                         ./modules/ModelProcessorx/DiagnosticHoriz/CreateNodesDiagnosticHoriz.cpp \
    1132                                         ./modules/ModelProcessorx/DiagnosticHoriz/CreateConstraintsDiagnosticHoriz.cpp \
    1133                                         ./modules/ModelProcessorx/DiagnosticHoriz/CreateLoadsDiagnosticHoriz.cpp\
    1134                                         ./modules/ModelProcessorx/DiagnosticVert/UpdateElementsDiagnosticVert.cpp\
    1135                                         ./modules/ModelProcessorx/DiagnosticVert/CreateNodesDiagnosticVert.cpp \
    1136                                         ./modules/ModelProcessorx/DiagnosticVert/CreateConstraintsDiagnosticVert.cpp \
    1137                                         ./modules/ModelProcessorx/DiagnosticVert/CreateLoadsDiagnosticVert.cpp\
    1138                                         ./modules/ModelProcessorx/DiagnosticHutter/UpdateElementsDiagnosticHutter.cpp\
    1139                                         ./modules/ModelProcessorx/DiagnosticHutter/CreateNodesDiagnosticHutter.cpp \
    1140                                         ./modules/ModelProcessorx/DiagnosticHutter/CreateConstraintsDiagnosticHutter.cpp \
    1141                                         ./modules/ModelProcessorx/DiagnosticHutter/CreateLoadsDiagnosticHutter.cpp\
    1142                                         ./modules/ModelProcessorx/BedSlope/UpdateElementsBedSlope.cpp\
    1143                                         ./modules/ModelProcessorx/BedSlope/CreateNodesBedSlope.cpp \
    1144                                         ./modules/ModelProcessorx/BedSlope/CreateConstraintsBedSlope.cpp\
    1145                                         ./modules/ModelProcessorx/BedSlope/CreateLoadsBedSlope.cpp\
    1146                                         ./modules/ModelProcessorx/SurfaceSlope/UpdateElementsSurfaceSlope.cpp\
    1147                                         ./modules/ModelProcessorx/SurfaceSlope/CreateNodesSurfaceSlope.cpp \
    1148                                         ./modules/ModelProcessorx/SurfaceSlope/CreateConstraintsSurfaceSlope.cpp\
    1149                                         ./modules/ModelProcessorx/SurfaceSlope/CreateLoadsSurfaceSlope.cpp\
    1150                                         ./modules/ModelProcessorx/Control/CreateParametersControl.cpp\
    1151                                         ./modules/ModelProcessorx/Control/UpdateElementsAndMaterialsControl.cpp\
    1152                                         ./modules/ModelProcessorx/Thermal/UpdateElementsThermal.cpp\
    1153                                         ./modules/ModelProcessorx/Thermal/CreateNodesThermal.cpp\
    1154                                         ./modules/ModelProcessorx/Thermal/CreateConstraintsThermal.cpp\
    1155                                         ./modules/ModelProcessorx/Thermal/CreateLoadsThermal.cpp\
    1156                                         ./modules/ModelProcessorx/Enthalpy/UpdateElementsEnthalpy.cpp\
    1157                                         ./modules/ModelProcessorx/Enthalpy/CreateNodesEnthalpy.cpp\
    1158                                         ./modules/ModelProcessorx/Enthalpy/CreateConstraintsEnthalpy.cpp\
    1159                                         ./modules/ModelProcessorx/Enthalpy/CreateLoadsEnthalpy.cpp\
    1160                                         ./modules/ModelProcessorx/Hydrology/UpdateElementsHydrology.cpp\
    1161                                         ./modules/ModelProcessorx/Hydrology/CreateNodesHydrology.cpp\
    1162                                         ./modules/ModelProcessorx/Hydrology/CreateConstraintsHydrology.cpp\
    1163                                         ./modules/ModelProcessorx/Hydrology/CreateLoadsHydrology.cpp\
    1164                                         ./modules/ModelProcessorx/Melting/UpdateElementsMelting.cpp\
    1165                                         ./modules/ModelProcessorx/Melting/CreateNodesMelting.cpp\
    1166                                         ./modules/ModelProcessorx/Melting/CreateConstraintsMelting.cpp\
    1167                                         ./modules/ModelProcessorx/Melting/CreateLoadsMelting.cpp\
    1168                                         ./modules/ModelProcessorx/Prognostic/UpdateElementsPrognostic.cpp\
    1169                                         ./modules/ModelProcessorx/Prognostic/CreateNodesPrognostic.cpp\
    1170                                         ./modules/ModelProcessorx/Prognostic/CreateConstraintsPrognostic.cpp\
    1171                                         ./modules/ModelProcessorx/Prognostic/CreateLoadsPrognostic.cpp\
    1172                                         ./modules/ModelProcessorx/Balancethickness/UpdateElementsBalancethickness.cpp\
    1173                                         ./modules/ModelProcessorx/Balancethickness/CreateNodesBalancethickness.cpp\
    1174                                         ./modules/ModelProcessorx/Balancethickness/CreateConstraintsBalancethickness.cpp\
    1175                                         ./modules/ModelProcessorx/Balancethickness/CreateLoadsBalancethickness.cpp\
    1176                                         ./modules/ModelProcessorx/Transient/UpdateElementsTransient.cpp\
    1177                                         ./modules/ModelProcessorx/Qmu/CreateParametersQmu.cpp\
    1178954                                        ./modules/ParsePetscOptionsx/ParsePetscOptionsx.h\
    1179955                                        ./modules/ParsePetscOptionsx/ParsePetscOptionsx.cpp\
     
    1182958                                        ./modules/NodalValuex/NodalValuex.h\
    1183959                                        ./modules/NodalValuex/NodalValuex.cpp\
    1184                                         ./modules/TriaSearchx/TriaSearchx.h\
    1185                                         ./modules/TriaSearchx/TriaSearchx.cpp\
    1186960                                        ./modules/VerticesDofx/VerticesDofx.h\
    1187961                                        ./modules/VerticesDofx/VerticesDofx.cpp\
    1188962                                        ./modules/OutputResultsx/OutputResultsx.h\
    1189963                                        ./modules/OutputResultsx/OutputResultsx.cpp\
    1190                                         ./modules/MinVelx/MinVelx.h\
    1191                                         ./modules/MinVelx/MinVelx.cpp\
    1192                                         ./modules/MaxVelx/MaxVelx.h\
    1193                                         ./modules/MaxVelx/MaxVelx.cpp\
    1194                                         ./modules/MaxAbsVxx/MaxAbsVxx.h\
    1195                                         ./modules/MaxAbsVxx/MaxAbsVxx.cpp\
    1196                                         ./modules/MaxAbsVyx/MaxAbsVyx.h\
    1197                                         ./modules/MaxAbsVyx/MaxAbsVyx.cpp\
    1198                                         ./modules/MaxAbsVzx/MaxAbsVzx.h\
    1199                                         ./modules/MaxAbsVzx/MaxAbsVzx.cpp\
    1200                                         ./modules/MaxVxx/MaxVxx.h\
    1201                                         ./modules/MaxVxx/MaxVxx.cpp\
    1202                                         ./modules/MaxVyx/MaxVyx.h\
    1203                                         ./modules/MaxVyx/MaxVyx.cpp\
    1204                                         ./modules/MaxVzx/MaxVzx.h\
    1205                                         ./modules/MaxVzx/MaxVzx.cpp\
    1206                                         ./modules/MinVxx/MinVxx.h\
    1207                                         ./modules/MinVxx/MinVxx.cpp\
    1208                                         ./modules/MinVyx/MinVyx.h\
    1209                                         ./modules/MinVyx/MinVyx.cpp\
    1210                                         ./modules/MinVzx/MinVzx.h\
    1211                                         ./modules/MinVzx/MinVzx.cpp\
    1212                                         ./modules/KMLMeshWritex/KMLFileReadx.h\
    1213                                         ./modules/KMLMeshWritex/KMLFileReadx.cpp\
    1214                                         ./modules/KMLMeshWritex/KMLMeshWritex.h\
    1215                                         ./modules/KMLMeshWritex/KMLMeshWritex.cpp\
    1216                                         ./modules/KMLOverlayx/KMLOverlayx.h\
    1217                                         ./modules/KMLOverlayx/KMLOverlayx.cpp\
    1218                                         ./modules/Xy2llx/Xy2llx.h\
    1219                                         ./modules/Xy2llx/Xy2llx.cpp\
    1220                                         ./modules/Ll2xyx/Ll2xyx.h\
    1221                                         ./modules/Ll2xyx/Ll2xyx.cpp\
    1222                                         ./modules/Exp2Kmlx/Exp2Kmlx.cpp\
    1223                                         ./modules/Exp2Kmlx/Exp2Kmlx.cpp\
    1224                                         ./modules/Kml2Expx/Kml2Expx.cpp\
    1225                                         ./modules/Kml2Expx/Kml2Expx.cpp\
    1226964                                        ./modules/InputDuplicatex/InputDuplicatex.h\
    1227965                                        ./modules/InputDuplicatex/InputDuplicatex.cpp\
    1228966                                        ./modules/InputScalex/InputScalex.h\
    1229967                                        ./modules/InputScalex/InputScalex.cpp\
    1230                                         ./modules/InputControlUpdatex/InputControlUpdatex.h\
    1231                                         ./modules/InputControlUpdatex/InputControlUpdatex.cpp\
    1232968                                        ./modules/SurfaceAreax/SurfaceAreax.h\
    1233969                                        ./modules/SurfaceAreax/SurfaceAreax.cpp\
    1234                                         ./modules/SurfaceAbsVelMisfitx/SurfaceAbsVelMisfitx.h\
    1235                                         ./modules/SurfaceAbsVelMisfitx/SurfaceAbsVelMisfitx.cpp\
    1236                                         ./modules/SurfaceRelVelMisfitx/SurfaceRelVelMisfitx.h\
    1237                                         ./modules/SurfaceRelVelMisfitx/SurfaceRelVelMisfitx.cpp\
    1238                                         ./modules/SurfaceLogVelMisfitx/SurfaceLogVelMisfitx.h\
    1239                                         ./modules/SurfaceLogVelMisfitx/SurfaceLogVelMisfitx.cpp\
    1240                                         ./modules/SurfaceLogVxVyMisfitx/SurfaceLogVxVyMisfitx.h\
    1241                                         ./modules/SurfaceLogVxVyMisfitx/SurfaceLogVxVyMisfitx.cpp\
    1242                                         ./modules/SurfaceAverageVelMisfitx/SurfaceAverageVelMisfitx.h\
    1243                                         ./modules/SurfaceAverageVelMisfitx/SurfaceAverageVelMisfitx.cpp\
    1244                                         ./modules/ThicknessAbsMisfitx/ThicknessAbsMisfitx.h\
    1245                                         ./modules/ThicknessAbsMisfitx/ThicknessAbsMisfitx.cpp\
    1246                                         ./modules/CostFunctionx/CostFunctionx.h\
    1247                                         ./modules/CostFunctionx/CostFunctionx.cpp\
    1248970                                        ./modules/CreateNodalConstraintsx/CreateNodalConstraintsx.h\
    1249971                                        ./modules/CreateNodalConstraintsx/CreateNodalConstraintsx.cpp\
    1250                                         ./modules/Orthx/Orthx.h\
    1251                                         ./modules/Orthx/Orthx.cpp\
    1252972                                        ./modules/UpdateDynamicConstraintsx/UpdateDynamicConstraintsx.h\
    1253973                                        ./modules/UpdateDynamicConstraintsx/UpdateDynamicConstraintsx.cpp\
    1254                                         ./modules/Gradjx/Gradjx.h\
    1255                                         ./modules/Gradjx/Gradjx.cpp\
    1256974                                        ./modules/IoModelToConstraintsx/IoModelToConstraintsx.h\
    1257975                                        ./modules/IoModelToConstraintsx/IoModelToConstraintsx.cpp\
    1258976                                        ./modules/InputUpdateFromConstantx/InputUpdateFromConstantx.h\
    1259977                                        ./modules/InputUpdateFromConstantx/InputUpdateFromConstantx.cpp\
    1260                                         ./modules/InputUpdateFromDakotax/InputUpdateFromDakotax.h\
    1261                                         ./modules/InputUpdateFromDakotax/InputUpdateFromDakotax.cpp\
    1262978                                        ./modules/InputUpdateFromSolutionx/InputUpdateFromSolutionx.h\
    1263979                                        ./modules/InputUpdateFromSolutionx/InputUpdateFromSolutionx.cpp\
    1264                                         ./modules/DakotaResponsesx/DakotaResponsesx.h\
    1265                                         ./modules/DakotaResponsesx/DakotaResponsesx.cpp\
    1266980                                        ./modules/GetSolutionFromInputsx/GetSolutionFromInputsx.h\
    1267981                                        ./modules/GetSolutionFromInputsx/GetSolutionFromInputsx.cpp\
     
    1270984                                        ./modules/InputUpdateFromVectorx/InputUpdateFromVectorx.h\
    1271985                                        ./modules/InputUpdateFromVectorx/InputUpdateFromVectorx.cpp\
    1272                                         ./modules/InputUpdateFromVectorDakotax/InputUpdateFromVectorDakotax.h\
    1273                                         ./modules/InputUpdateFromVectorDakotax/InputUpdateFromVectorDakotax.cpp\
    1274986                                        ./modules/InputArtificialNoisex/InputArtificialNoisex.h\
    1275987                                        ./modules/InputArtificialNoisex/InputArtificialNoisex.cpp\
     
    12881000                                        ./modules/UpdateConstraintsx/UpdateConstraintsx.h\
    12891001                                        ./modules/UpdateConstraintsx/UpdateConstraintsx.cpp\
    1290                                         ./modules/InterpFromGridToMeshx/InterpFromGridToMeshx.cpp\
    1291                                         ./modules/InterpFromGridToMeshx/InterpFromGridToMeshx.h\
    1292                                         ./modules/InterpFromMesh2dx/InterpFromMesh2dx.cpp\
    1293                                         ./modules/InterpFromMesh2dx/InterpFromMesh2dxt.cpp\
    1294                                         ./modules/InterpFromMesh2dx/InterpFromMesh2dx.h\
    1295                                         ./modules/InterpFromMeshToMesh2dx/InterpFromMeshToMesh2dx.cpp\
    1296                                         ./modules/InterpFromMeshToMesh2dx/InterpFromMeshToMesh2dx.h\
    1297                                         ./modules/InterpFromMeshToMesh3dx/InterpFromMeshToMesh3dx.cpp\
    1298                                         ./modules/InterpFromMeshToMesh3dx/InterpFromMeshToMesh3dx.h\
    1299                                         ./modules/InterpFromMeshToGridx/InterpFromMeshToGridx.cpp\
    1300                                         ./modules/InterpFromMeshToGridx/InterpFromMeshToGridx.h\
    1301                                         ./modules/HoleFillerx/HoleFillerx.cpp\
    1302                                         ./modules/HoleFillerx/HoleFillerx.h\
    1303                                         ./modules/AverageFilterx/AverageFilterx.cpp\
    1304                                         ./modules/AverageFilterx/AverageFilterx.h\
    1305                                         ./modules/AverageOntoPartitionx/AverageOntoPartitionx.cpp\
    1306                                         ./modules/AverageOntoPartitionx/AverageOntoPartitionx.h\
    13071002                                        ./modules/MeshPartitionx/MeshPartitionx.cpp\
    13081003                                        ./modules/MeshPartitionx/MeshPartitionx.h\
    1309                                         ./modules/MeshProfileIntersectionx/MeshProfileIntersectionx.cpp\
    1310                                         ./modules/MeshProfileIntersectionx/MeshProfileIntersectionx.h\
    1311                                         ./modules/MeshProfileIntersectionx/MeshSegmentsIntersection.cpp\
    1312                                         ./modules/MeshProfileIntersectionx/ElementSegmentsIntersection.cpp\
    1313                                         ./modules/MeshProfileIntersectionx/ElementSegment.cpp\
    1314                                         ./modules/MeshProfileIntersectionx/SegmentIntersect.cpp\
    1315                                         ./modules/MeshProfileIntersectionx/NodeInElement.cpp\
    1316                                         ./modules/ContourToMeshx/ContourToMeshx.cpp\
    1317                                         ./modules/ContourToMeshx/ContourToMeshxt.cpp\
    1318                                         ./modules/ContourToMeshx/ContourToMeshx.h\
    1319                                         ./modules/Reducevectorgtosx/Reducevectorgtosx.cpp\
    1320                                         ./modules/Reducevectorgtosx/Reducevectorgtosx.h\
    13211004                                        ./modules/Reducevectorgtofx/Reducevectorgtofx.cpp\
    13221005                                        ./modules/Reducevectorgtofx/Reducevectorgtofx.h\
     
    13271010                                        ./modules/StringToEnumx/StringToEnumx.cpp\
    13281011                                        ./modules/StringToEnumx/StringToEnumx.h\
    1329                                         ./modules/MassFluxx/MassFluxx.cpp\
    1330                                         ./modules/MassFluxx/MassFluxx.h\
    1331                                         ./modules/ControlInputGetGradientx/ControlInputGetGradientx.cpp\
    1332                                         ./modules/ControlInputGetGradientx/ControlInputGetGradientx.h\
    1333                                         ./modules/ControlInputSetGradientx/ControlInputSetGradientx.cpp\
    1334                                         ./modules/ControlInputSetGradientx/ControlInputSetGradientx.h\
    1335                                         ./modules/ControlInputScaleGradientx/ControlInputScaleGradientx.cpp\
    1336                                         ./modules/ControlInputScaleGradientx/ControlInputScaleGradientx.h\
    13371012                                        ./modules/SystemMatricesx/SystemMatricesx.cpp\
    13381013                                        ./modules/SystemMatricesx/SystemMatricesx.h\
     
    13401015                                        ./modules/ConstraintsStatex/ConstraintsStatex.h\
    13411016                                        ./modules/ConstraintsStatex/ConstraintsStateLocal.h\
    1342                                         ./modules/ConstraintsStatex/RiftConstraintsState.cpp\
    1343                                         ./modules/ConstraintsStatex/ThermalConstraintsState.cpp\
    1344                                         ./modules/ConstraintsStatex/ThermalIsPresent.cpp\
    13451017                                        ./modules/Responsex/Responsex.h\
    13461018                                        ./modules/Responsex/Responsex.cpp\
     
    13491021                                        ./modules/ResetConstraintsx/ResetConstraintsx.h\
    13501022                                        ./modules/ResetConstraintsx/ResetConstraintsx.cpp\
    1351                                         ./modules/ResetConstraintsx/ThermalConstraintsReset.cpp\
    13521023                                        ./modules/Solverx/Solverx.cpp\
    13531024                                        ./modules/Solverx/Solverx.h\
     
    13551026                                        ./modules/VecMergex/VecMergex.cpp\
    13561027                                        ./modules/VecMergex/VecMergex.h\
    1357                                         ./modules/Scotchx/Scotchx.cpp\
    1358                                         ./modules/Scotchx/Scotchx.h\
    13591028                                        ./modules/Mergesolutionfromftogx/Mergesolutionfromftogx.cpp\
    13601029                                        ./modules/Mergesolutionfromftogx/Mergesolutionfromftogx.h\
    1361                                         ./modules/Dakotax/Dakotax.h\
    1362                                         ./modules/Dakotax/Dakotax.cpp\
    1363                                         ./modules/Dakotax/DakotaMPI_Bcast.cpp\
    1364                                         ./modules/Dakotax/DakotaFree.cpp\
    1365                                         ./modules/Dakotax/SpawnCore.cpp\
    1366                                         ./modules/Dakotax/SpawnCoreParallel.cpp\
    1367                                         ./modules/Dakotax/DescriptorIndex.cpp\
    13681030                                        ./modules/InputToResultx/InputToResultx.cpp\
    13691031                                        ./modules/InputToResultx/InputToResultx.h\
    13701032                                        ./modules/InputConvergencex/InputConvergencex.cpp\
    13711033                                        ./modules/InputConvergencex/InputConvergencex.h\
    1372                                         ./modules/OutputRiftsx/OutputRiftsx.h\
    1373                                         ./modules/OutputRiftsx/OutputRiftsx.cpp\
    1374                                         ./modules/DragCoefficientAbsGradientx/DragCoefficientAbsGradientx.cpp\
    1375                                         ./modules/DragCoefficientAbsGradientx/DragCoefficientAbsGradientx.h\
    1376                                         ./modules/ThicknessAbsGradientx/ThicknessAbsGradientx.cpp\
    1377                                         ./modules/ThicknessAbsGradientx/ThicknessAbsGradientx.h\
    1378                                         ./modules/RheologyBbarAbsGradientx/RheologyBbarAbsGradientx.cpp\
    1379                                         ./modules/RheologyBbarAbsGradientx/RheologyBbarAbsGradientx.h\
    1380                                         ./modules/RheologyBbarx/RheologyBbarx.cpp\
    1381                                         ./modules/RheologyBbarx/RheologyBbarx.h\
    1382                                         ./solutions/diagnostic_core.cpp\
    13831034                                        ./solutions/convergence.cpp\
    1384                                         ./solutions/thermal_core.cpp\
    1385                                         ./solutions/thermal_core_step.cpp\
    1386                                         ./solutions/enthalpy_core.cpp\
    13871035                                        ./solutions/WriteLockFile.cpp\
    1388                                         ./solutions/control_core.cpp\
    1389                                         ./solutions/controltao_core.cpp\
    1390                                         ./solutions/controlrestart.cpp\
    1391                                         ./solutions/controlconvergence.cpp\
    1392                                         ./solutions/objectivefunctionC.cpp\
    1393                                         ./solutions/gradient_core.cpp\
    1394                                         ./solutions/adjointdiagnostic_core.cpp\
    1395                                         ./solutions/adjointbalancethickness_core.cpp\
    1396                                         ./solutions/prognostic_core.cpp\
    1397                                         ./solutions/balancethickness_core.cpp\
    1398                                         ./solutions/surfaceslope_core.cpp\
    1399                                         ./solutions/bedslope_core.cpp\
    1400                                         ./solutions/hydrology_core.cpp\
    1401                                         ./solutions/hydrology_core_step.cpp\
    1402                                         ./solutions/transient_core.cpp\
    1403                                         ./solutions/groundinglinemigration2d_core.cpp\
    1404                                         ./solutions/steadystate_core.cpp\
    1405                                         ./solutions/steadystateconvergence.cpp\
    14061036                                        ./solutions/ResetBoundaryConditions.cpp\
    14071037                                        ./solutions/AnalysisConfiguration.cpp\
    14081038                                        ./solutions/CorePointerFromSolutionEnum.cpp\
    1409                                         ./solutions/AdjointCorePointerFromSolutionEnum.cpp\
    14101039                                        ./solvers/solver_linear.cpp\
    1411                                         ./solvers/solver_adjoint_linear.cpp\
    1412                                         ./solvers/solver_nonlinear.cpp\
    1413                                         ./solvers/solver_stokescoupling_nonlinear.cpp\
    1414                                         ./solvers/solver_thermal_nonlinear.cpp\
    1415                                         ./modules/Bamgx/Bamgx.cpp\
    1416                                         ./modules/Bamgx/Bamgx.h\
    1417                                         ./modules/BamgConvertMeshx/BamgConvertMeshx.cpp\
    1418                                         ./modules/BamgConvertMeshx/BamgConvertMeshx.h
    1419 
    1420 libpISSM_a_CXXFLAGS = -fPIC -D_PARALLEL_   -D_C_ $(CXXOPTFLAGS)
     1040                                        ./solvers/solver_nonlinear.cpp
     1041
     1042
     1043libpISSM_a_CXXFLAGS = -fPIC -D_PARALLEL_   -D_C_ $(CXXOPTFLAGS)
     1044#}}}
     1045#Overload library, to overload any non-standard symbols. {{{1
     1046libOverload_a_SOURCES = ./shared/String/stricmp.c
     1047libOverload_a_CFLAGS = -fPIC -D_PARALLEL_   -D_C_ $(COPTFLAGS)
     1048#}}}
     1049#DAKOTA sources  {{{1
     1050if DAKOTA
     1051libpISSM_a_SOURCES +=  ./objects/DakotaPlugin.h\
     1052                                          ./objects/DakotaPlugin.cpp\
     1053                                          ./modules/InputUpdateFromDakotax/InputUpdateFromDakotax.h\
     1054                                          ./modules/InputUpdateFromDakotax/InputUpdateFromDakotax.cpp\
     1055                                          ./modules/DakotaResponsesx/DakotaResponsesx.h\
     1056                                          ./modules/DakotaResponsesx/DakotaResponsesx.cpp\
     1057                                          ./modules/InputUpdateFromVectorDakotax/InputUpdateFromVectorDakotax.h\
     1058                                          ./modules/InputUpdateFromVectorDakotax/InputUpdateFromVectorDakotax.cpp\
     1059                                          ./modules/AverageOntoPartitionx/AverageOntoPartitionx.cpp\
     1060                                          ./modules/AverageOntoPartitionx/AverageOntoPartitionx.h\
     1061                                          ./modules/Dakotax/Dakotax.h\
     1062                                          ./modules/Dakotax/Dakotax.cpp\
     1063                                          ./modules/Dakotax/DakotaMPI_Bcast.cpp\
     1064                                          ./modules/Dakotax/DakotaFree.cpp\
     1065                                          ./modules/Dakotax/SpawnCore.cpp\
     1066                                          ./modules/Dakotax/SpawnCoreParallel.cpp\
     1067                                          ./modules/Dakotax/DescriptorIndex.cpp\
     1068                                          ./modules/AverageOntoPartitionx/AverageOntoPartitionx.cpp\
     1069                                          ./modules/ModelProcessorx/Qmu/CreateParametersQmu.cpp\
     1070                                          ./modules/AverageOntoPartitionx/AverageOntoPartitionx.h
     1071endif
     1072#}}}
     1073#Transient sources  {{{1
     1074if TRANSIENT
     1075libpISSM_a_SOURCES +=  ./solutions/transient_core.cpp\
     1076                                           ./modules/ModelProcessorx/Transient/UpdateElementsTransient.cpp
     1077endif
     1078#}}}
     1079#Steadystate sources  {{{1
     1080if STEADYSTATE
     1081libpISSM_a_SOURCES += ./solutions/steadystate_core.cpp\
     1082                                          ./solutions/steadystateconvergence.cpp
     1083endif
     1084#}}}
     1085#Prognostic sources  {{{1
     1086if PROGNOSTIC
     1087libpISSM_a_SOURCES +=  ./solutions/prognostic_core.cpp\
     1088                                           ./modules/ModelProcessorx/Prognostic/UpdateElementsPrognostic.cpp\
     1089                                           ./modules/ModelProcessorx/Prognostic/CreateNodesPrognostic.cpp\
     1090                                           ./modules/ModelProcessorx/Prognostic/CreateConstraintsPrognostic.cpp\
     1091                                           ./modules/ModelProcessorx/Prognostic/CreateLoadsPrognostic.cpp
     1092
     1093endif
     1094#}}}
     1095#Thermal sources  {{{1
     1096if THERMAL
     1097libpISSM_a_SOURCES +=  ./solutions/thermal_core.cpp\
     1098                                           ./solutions/thermal_core_step.cpp\
     1099                                           ./solutions/enthalpy_core.cpp\
     1100                                           ./solvers/solver_thermal_nonlinear.cpp\
     1101                                           ./modules/ModelProcessorx/Thermal/UpdateElementsThermal.cpp\
     1102                                           ./modules/ModelProcessorx/Thermal/CreateNodesThermal.cpp\
     1103                                           ./modules/ModelProcessorx/Thermal/CreateConstraintsThermal.cpp\
     1104                                           ./modules/ModelProcessorx/Thermal/CreateLoadsThermal.cpp\
     1105                                           ./modules/ModelProcessorx/Enthalpy/UpdateElementsEnthalpy.cpp\
     1106                                           ./modules/ModelProcessorx/Enthalpy/CreateNodesEnthalpy.cpp\
     1107                                           ./modules/ModelProcessorx/Enthalpy/CreateConstraintsEnthalpy.cpp\
     1108                                           ./modules/ModelProcessorx/Enthalpy/CreateLoadsEnthalpy.cpp\
     1109                                           ./modules/ModelProcessorx/Melting/UpdateElementsMelting.cpp\
     1110                                           ./modules/ModelProcessorx/Melting/CreateNodesMelting.cpp\
     1111                                           ./modules/ModelProcessorx/Melting/CreateConstraintsMelting.cpp\
     1112                                           ./modules/ModelProcessorx/Melting/CreateLoadsMelting.cpp\
     1113                                           ./modules/ConstraintsStatex/ThermalConstraintsState.cpp\
     1114                                           ./modules/ConstraintsStatex/ThermalIsPresent.cpp\
     1115                                           ./modules/ResetConstraintsx/ThermalConstraintsReset.cpp
     1116endif
     1117#}}}
     1118#Control sources  {{{1
     1119if CONTROL
     1120libpISSM_a_SOURCES += ./solutions/control_core.cpp\
     1121                                          ./solutions/controltao_core.cpp\
     1122                                          ./solutions/controlrestart.cpp\
     1123                                          ./solutions/controlconvergence.cpp\
     1124                                          ./solutions/objectivefunctionC.cpp\
     1125                                          ./solutions/gradient_core.cpp\
     1126                                          ./solutions/adjointdiagnostic_core.cpp\
     1127                                          ./solutions/adjointbalancethickness_core.cpp\
     1128                                          ./solutions/AdjointCorePointerFromSolutionEnum.cpp\
     1129                                          ./solvers/solver_adjoint_linear.cpp\
     1130                                          ./modules/ControlInputGetGradientx/ControlInputGetGradientx.cpp\
     1131                                          ./modules/ControlInputGetGradientx/ControlInputGetGradientx.h\
     1132                                          ./modules/ControlInputSetGradientx/ControlInputSetGradientx.cpp\
     1133                                          ./modules/ControlInputSetGradientx/ControlInputSetGradientx.h\
     1134                                          ./modules/ControlInputScaleGradientx/ControlInputScaleGradientx.cpp\
     1135                                          ./modules/ControlInputScaleGradientx/ControlInputScaleGradientx.h\
     1136                                          ./modules/ModelProcessorx/Control/CreateParametersControl.cpp\
     1137                                          ./modules/ModelProcessorx/Control/UpdateElementsAndMaterialsControl.cpp\
     1138                                          ./modules/InputControlUpdatex/InputControlUpdatex.h\
     1139                                          ./modules/InputControlUpdatex/InputControlUpdatex.cpp\
     1140                                          ./modules/SurfaceAbsVelMisfitx/SurfaceAbsVelMisfitx.h\
     1141                                          ./modules/SurfaceAbsVelMisfitx/SurfaceAbsVelMisfitx.cpp\
     1142                                          ./modules/SurfaceRelVelMisfitx/SurfaceRelVelMisfitx.h\
     1143                                          ./modules/SurfaceRelVelMisfitx/SurfaceRelVelMisfitx.cpp\
     1144                                          ./modules/SurfaceLogVelMisfitx/SurfaceLogVelMisfitx.h\
     1145                                          ./modules/SurfaceLogVelMisfitx/SurfaceLogVelMisfitx.cpp\
     1146                                          ./modules/SurfaceLogVxVyMisfitx/SurfaceLogVxVyMisfitx.h\
     1147                                          ./modules/SurfaceLogVxVyMisfitx/SurfaceLogVxVyMisfitx.cpp\
     1148                                          ./modules/SurfaceAverageVelMisfitx/SurfaceAverageVelMisfitx.h\
     1149                                          ./modules/SurfaceAverageVelMisfitx/SurfaceAverageVelMisfitx.cpp\
     1150                                          ./modules/ThicknessAbsMisfitx/ThicknessAbsMisfitx.h\
     1151                                          ./modules/ThicknessAbsMisfitx/ThicknessAbsMisfitx.cpp\
     1152                                          ./modules/CostFunctionx/CostFunctionx.h\
     1153                                          ./modules/CostFunctionx/CostFunctionx.cpp\
     1154                                          ./modules/Orthx/Orthx.h\
     1155                                          ./modules/Orthx/Orthx.cpp\
     1156                                          ./modules/Gradjx/Gradjx.h\
     1157                                          ./modules/Gradjx/Gradjx.cpp\
     1158                                          ./modules/DragCoefficientAbsGradientx/DragCoefficientAbsGradientx.cpp\
     1159                                          ./modules/DragCoefficientAbsGradientx/DragCoefficientAbsGradientx.h\
     1160                                          ./modules/ThicknessAbsGradientx/ThicknessAbsGradientx.cpp\
     1161                                          ./modules/ThicknessAbsGradientx/ThicknessAbsGradientx.h\
     1162                                          ./modules/RheologyBbarAbsGradientx/RheologyBbarAbsGradientx.cpp\
     1163                                          ./modules/RheologyBbarAbsGradientx/RheologyBbarAbsGradientx.h\
     1164                                          ./objects/Inputs/ControlInput.h\
     1165                                          ./objects/Inputs/ControlInput.cpp\
     1166                                          ./shared/Numerics/BrentSearch.cpp\
     1167                                          ./shared/Numerics/OptimalSearch.cpp\
     1168                                          ./shared/Numerics/OptFunc.cpp
     1169endif
     1170#}}}
     1171#Hydrology sources  {{{1
     1172if HYDROLOGY
     1173libpISSM_a_SOURCES += ./modules/ModelProcessorx/Hydrology/UpdateElementsHydrology.cpp\
     1174                                          ./modules/ModelProcessorx/Hydrology/CreateNodesHydrology.cpp\
     1175                                          ./modules/ModelProcessorx/Hydrology/CreateConstraintsHydrology.cpp\
     1176                                          ./modules/ModelProcessorx/Hydrology/CreateLoadsHydrology.cpp\
     1177                                          ./solutions/hydrology_core.cpp\
     1178                                          ./solutions/hydrology_core_step.cpp
     1179endif
     1180#}}}
     1181#Diagnostic sources  {{{1
     1182if DIAGNOSTIC
     1183libpISSM_a_SOURCES += ./modules/ModelProcessorx/DiagnosticHoriz/UpdateElementsDiagnosticHoriz.cpp\
     1184                                          ./modules/ModelProcessorx/DiagnosticHoriz/CreateNodesDiagnosticHoriz.cpp \
     1185                                          ./modules/ModelProcessorx/DiagnosticHoriz/CreateConstraintsDiagnosticHoriz.cpp \
     1186                                          ./modules/ModelProcessorx/DiagnosticHoriz/CreateLoadsDiagnosticHoriz.cpp\
     1187                                          ./modules/ModelProcessorx/DiagnosticVert/UpdateElementsDiagnosticVert.cpp\
     1188                                          ./modules/ModelProcessorx/DiagnosticVert/CreateNodesDiagnosticVert.cpp \
     1189                                          ./modules/ModelProcessorx/DiagnosticVert/CreateConstraintsDiagnosticVert.cpp \
     1190                                          ./modules/ModelProcessorx/DiagnosticVert/CreateLoadsDiagnosticVert.cpp\
     1191                                          ./modules/ModelProcessorx/DiagnosticHutter/UpdateElementsDiagnosticHutter.cpp\
     1192                                          ./modules/ModelProcessorx/DiagnosticHutter/CreateNodesDiagnosticHutter.cpp \
     1193                                          ./modules/ModelProcessorx/DiagnosticHutter/CreateConstraintsDiagnosticHutter.cpp \
     1194                                          ./modules/ModelProcessorx/DiagnosticHutter/CreateLoadsDiagnosticHutter.cpp\
     1195                                          ./solutions/diagnostic_core.cpp\
     1196                                          ./solvers/solver_stokescoupling_nonlinear.cpp
     1197endif
     1198#}}}
     1199#Balanced sources  {{{1
     1200if BALANCED
     1201libpISSM_a_SOURCES += ./modules/ModelProcessorx/Balancethickness/UpdateElementsBalancethickness.cpp\
     1202                                          ./modules/ModelProcessorx/Balancethickness/CreateNodesBalancethickness.cpp\
     1203                                          ./modules/ModelProcessorx/Balancethickness/CreateConstraintsBalancethickness.cpp\
     1204                                          ./modules/ModelProcessorx/Balancethickness/CreateLoadsBalancethickness.cpp\
     1205                                          ./solutions/balancethickness_core.cpp
     1206endif
     1207#}}}
     1208#Responses sources  {{{1
     1209if RESPONSES
     1210libpISSM_a_SOURCES += ./modules/MinVelx/MinVelx.h\
     1211                                          ./modules/MinVelx/MinVelx.cpp\
     1212                                          ./modules/MaxVelx/MaxVelx.h\
     1213                                          ./modules/MaxVelx/MaxVelx.cpp\
     1214                                          ./modules/MaxAbsVxx/MaxAbsVxx.h\
     1215                                          ./modules/MaxAbsVxx/MaxAbsVxx.cpp\
     1216                                          ./modules/MaxAbsVyx/MaxAbsVyx.h\
     1217                                          ./modules/MaxAbsVyx/MaxAbsVyx.cpp\
     1218                                          ./modules/MaxAbsVzx/MaxAbsVzx.h\
     1219                                          ./modules/MaxAbsVzx/MaxAbsVzx.cpp\
     1220                                          ./modules/MaxVxx/MaxVxx.h\
     1221                                          ./modules/MaxVxx/MaxVxx.cpp\
     1222                                          ./modules/MaxVyx/MaxVyx.h\
     1223                                          ./modules/MaxVyx/MaxVyx.cpp\
     1224                                          ./modules/MaxVzx/MaxVzx.h\
     1225                                          ./modules/MaxVzx/MaxVzx.cpp\
     1226                                          ./modules/MinVxx/MinVxx.h\
     1227                                          ./modules/MinVxx/MinVxx.cpp\
     1228                                          ./modules/MinVyx/MinVyx.h\
     1229                                          ./modules/MinVyx/MinVyx.cpp\
     1230                                          ./modules/MinVzx/MinVzx.h\
     1231                                          ./modules/MinVzx/MinVzx.cpp\
     1232                                          ./modules/RheologyBbarx/RheologyBbarx.cpp\
     1233                                          ./modules/RheologyBbarx/RheologyBbarx.h\
     1234                                          ./modules/MassFluxx/MassFluxx.cpp\
     1235                                          ./modules/MassFluxx/MassFluxx.h
     1236endif
     1237#}}}
     1238#Slope sources  {{{1
     1239if SLOPE
     1240libpISSM_a_SOURCES += ./modules/ModelProcessorx/BedSlope/UpdateElementsBedSlope.cpp\
     1241                                          ./modules/ModelProcessorx/BedSlope/CreateNodesBedSlope.cpp \
     1242                                          ./modules/ModelProcessorx/BedSlope/CreateConstraintsBedSlope.cpp\
     1243                                          ./modules/ModelProcessorx/BedSlope/CreateLoadsBedSlope.cpp\
     1244                                          ./modules/ModelProcessorx/SurfaceSlope/UpdateElementsSurfaceSlope.cpp\
     1245                                          ./modules/ModelProcessorx/SurfaceSlope/CreateNodesSurfaceSlope.cpp \
     1246                                          ./modules/ModelProcessorx/SurfaceSlope/CreateConstraintsSurfaceSlope.cpp\
     1247                                          ./modules/ModelProcessorx/SurfaceSlope/CreateLoadsSurfaceSlope.cpp\
     1248                                          ./solutions/surfaceslope_core.cpp\
     1249                                          ./solutions/bedslope_core.cpp
     1250endif
     1251#}}}
     1252#GroundingLine sources  {{{1
     1253if GROUNDINGLINE
     1254libpISSM_a_SOURCES += ./modules/GroundingLineMigrationx/GroundingLineMigrationx.cpp\
     1255                                          ./modules/GroundingLineMigrationx/GroundingLineMigrationx.h\
     1256                                          ./modules/GroundingLineMigrationx/GroundingLineMigrationxLocal.h\
     1257                                          ./modules/GroundingLineMigrationx/GroundingLineMigrationxUtils.cpp\
     1258                                          ./solutions/groundinglinemigration2d_core.cpp
     1259endif
     1260#}}}
     1261#Rifts sources  {{{1
     1262if RIFTS
     1263libpISSM_a_SOURCES += ./objects/Loads/Riftfront.cpp\
     1264                                          ./objects/Loads/Riftfront.h\
     1265                                          ./modules/ConstraintsStatex/RiftConstraintsState.cpp
     1266endif
     1267#}}}
     1268#3D sources  {{{1
     1269if THREED
     1270libpISSM_a_SOURCES += ./objects/Gauss/GaussPenta.h\
     1271                                          ./objects/Gauss/GaussPenta.cpp\
     1272                                          ./objects/ElementResults/PentaVertexElementResult.h\
     1273                                          ./objects/ElementResults/PentaVertexElementResult.cpp\
     1274                                          ./objects/Inputs/PentaVertexInput.h\
     1275                                          ./objects/Inputs/PentaVertexInput.cpp\
     1276                                          ./objects/Elements/Penta.h\
     1277                                          ./objects/Elements/Penta.cpp\
     1278                                          ./objects/Elements/PentaHook.h\
     1279                                          ./objects/Elements/PentaHook.cpp\
     1280                                          ./objects/Elements/PentaRef.h\
     1281                                          ./objects/Elements/PentaRef.cpp
     1282endif
     1283#}}}
     1284
     1285#Executable {{{1
    14211286
    14221287if NOPARALLEL
     
    14261291endif
    14271292
    1428 LDADD =    ./libpISSM.a $(PETSCLIB) $(TAOLIB) $(FLIBS) $(PLAPACKLIB)  $(MUMPSLIB) $(SCALAPACKLIB)  $(BLACSLIB) $(HYPRELIB) $(MLLIB) $(DAKOTALIB) $(METISLIB) $(CHACOLIB) $(SCOTCHLIB) $(BLASLAPACKLIB)  $(MKLLIB) $(MPILIB) $(MATHLIB) $(FORTRANLIB) $(GRAPHICSLIB) libOverload.a $(MULTITHREADINGLIB)
     1293#Standard libraries
     1294LDADD =      ./libpISSM.a ./libOverload.a
     1295
     1296if AD
     1297LDADD +=    ./libAD.a
     1298endif
     1299
     1300#External packages
     1301LDADD += $(PETSCLIB) $(TAOLIB) $(FLIBS) $(PLAPACKLIB)  $(MUMPSLIB) $(SCALAPACKLIB)  $(BLACSLIB) $(HYPRELIB) $(MLLIB) $(DAKOTALIB) $(METISLIB) $(CHACOLIB) $(SCOTCHLIB) $(BLASLAPACKLIB)  $(MKLLIB) $(MPILIB) $(MATHLIB) $(FORTRANLIB) $(GRAPHICSLIB) $(MULTITHREADINGLIB) $(ADICLIB)
     1302
    14291303
    14301304issm_exe_SOURCES = solutions/issm.cpp
    1431 issm_exe_CXXFLAGS= -fPIC -D_PARALLEL_  $(CXXOPTFLAGS) $(COPTFLAGS)
     1305issm_exe_CXXFLAGS= -fPIC -D_PARALLEL_  $(CXXOPTFLAGS) $(COPTFLAGS)
     1306
     1307#}}}
     1308
  • issm/trunk/src/c/modules/Dakotax/SpawnCoreParallel.cpp

    r9761 r9775  
    6969        _printf_(VerboseQmu(),"%s%s%s\n","Starting ",EnumToStringx(solution_type)," core:");
    7070        CorePointerFromSolutionEnum(&solutioncore,femmodel->parameters,solution_type);
     71        #ifdef _HAVE_CONTROL_
    7172        if(control_analysis)solutioncore=&control_core;
     73        #else
     74        _error_("ISSM was not compiled with control capabilities, exiting!");
     75        #endif
    7276
    7377        /*Run the core solution sequence: */
  • issm/trunk/src/c/modules/ModelProcessorx/CreateDataSets.cpp

    r9761 r9775  
    3232        /*Now, branch onto analysis dependent model generation: */
    3333        switch(analysis_type){
     34
     35                #ifdef _HAVE_DIAGNOSTIC_
    3436                case DiagnosticHorizAnalysisEnum:
    3537                        CreateNodesDiagnosticHoriz(pnodes, iomodel);
     
    5254                        UpdateElementsDiagnosticHutter(elements,iomodel,analysis_counter,analysis_type);
    5355                        break;
    54 
    55                 case BedSlopeAnalysisEnum:
    56                         CreateNodesBedSlope(pnodes, iomodel);
    57                         CreateConstraintsBedSlope(pconstraints,iomodel);
    58                         CreateLoadsBedSlope(ploads,iomodel);
    59                         UpdateElementsBedSlope(elements,iomodel,analysis_counter,analysis_type);
    60                         break;
    61 
    62                 case SurfaceSlopeAnalysisEnum:
    63                         CreateNodesSurfaceSlope(pnodes, iomodel);
    64                         CreateConstraintsSurfaceSlope(pconstraints,iomodel);
    65                         CreateLoadsSurfaceSlope(ploads,iomodel);
    66                         UpdateElementsSurfaceSlope(elements,iomodel,analysis_counter,analysis_type);
    67                         break;
    68 
     56                #endif
     57               
     58                #ifdef _HAVE_HYDROLOGY_
    6959                case HydrologyAnalysisEnum:
    7060                        CreateNodesHydrology(pnodes, iomodel);
     
    7363                        UpdateElementsHydrology(elements,iomodel,analysis_counter,analysis_type);
    7464                        break;
     65                #endif
    7566
    7667                #ifdef _HAVE_THERMAL_
     
    9788                #endif
    9889
     90                #ifdef _HAVE_BALANCED_
     91                case BalancethicknessAnalysisEnum:
     92                        CreateNodesBalancethickness(pnodes, iomodel);
     93                        CreateConstraintsBalancethickness(pconstraints,iomodel);
     94                        CreateLoadsBalancethickness(ploads,iomodel);
     95                        UpdateElementsBalancethickness(elements,iomodel,analysis_counter,analysis_type);
     96                        break;
     97                #endif
     98
     99                #ifdef _HAVE_SLOPE_
     100                case BedSlopeAnalysisEnum:
     101                        CreateNodesBedSlope(pnodes, iomodel);
     102                        CreateConstraintsBedSlope(pconstraints,iomodel);
     103                        CreateLoadsBedSlope(ploads,iomodel);
     104                        UpdateElementsBedSlope(elements,iomodel,analysis_counter,analysis_type);
     105                        break;
     106
     107                case SurfaceSlopeAnalysisEnum:
     108                        CreateNodesSurfaceSlope(pnodes, iomodel);
     109                        CreateConstraintsSurfaceSlope(pconstraints,iomodel);
     110                        CreateLoadsSurfaceSlope(ploads,iomodel);
     111                        UpdateElementsSurfaceSlope(elements,iomodel,analysis_counter,analysis_type);
     112                        break;
     113                #endif
     114
     115                #ifdef _HAVE_PROGNOSTIC_
    99116                case PrognosticAnalysisEnum:
    100117                        CreateNodesPrognostic(pnodes, iomodel);
     
    103120                        UpdateElementsPrognostic(elements,iomodel,analysis_counter,analysis_type);
    104121                        break;
     122                #endif
    105123
    106                 case BalancethicknessAnalysisEnum:
    107                         CreateNodesBalancethickness(pnodes, iomodel);
    108                         CreateConstraintsBalancethickness(pconstraints,iomodel);
    109                         CreateLoadsBalancethickness(ploads,iomodel);
    110                         UpdateElementsBalancethickness(elements,iomodel,analysis_counter,analysis_type);
    111                         break;
    112124
    113125                default:
     
    124136
    125137        /*Update Elements in case we are running a transient solution: */
     138        #ifdef _HAVE_TRANSIENT_
    126139        parameters=*pparameters;
    127140        if(analysis_counter==(nummodels-1)&& solution_type==TransientSolutionEnum){
    128141                UpdateElementsTransient(elements,parameters,iomodel,analysis_counter,analysis_type);
    129142        }
     143        #endif
    130144
    131145        /*Sort datasets: */
  • issm/trunk/src/c/modules/ModelProcessorx/CreateElementsVerticesAndMaterials.cpp

    r9734 r9775  
    4646        /*Fetch data needed: */
    4747        iomodel->FetchData(4,MeshElementsEnum,MeshElementconnectivityEnum,MaterialsRheologyBEnum,MaterialsRheologyNEnum);
     48        #ifdef _HAVE_THREED_
    4849        if(dim==3)          iomodel->FetchData(2,MeshUpperelementsEnum,MeshLowerelementsEnum);
     50        #endif
    4951        if(control_analysis)iomodel->FetchData(3,InversionControlParametersEnum,InversionMinParametersEnum,InversionMaxParametersEnum);
    5052       
     
    5557                        /*Create and add tria element to elements dataset: */
    5658                        if(dim==2) elements->AddObject(new Tria(i+1,i,i,iomodel,nummodels));
     59                #ifdef _HAVE_THREED_
    5760                        else       elements->AddObject(new Penta(i+1,i,i,iomodel,nummodels));
     61                #endif
    5862
    5963                        /*Create and add material property to materials dataset: */
  • issm/trunk/src/c/modules/Responsex/Responsex.cpp

    r9636 r9775  
    1919
    2020        switch (StringToEnumx(response_descriptor)){
    21                
     21
     22                #ifdef _HAVE_RESPONSES_
    2223                case MinVelEnum:                 MinVelx(                  responses, elements,nodes, vertices, loads, materials, parameters,process_units); break;
    2324                case MaxVelEnum:                 MaxVelx(                  responses, elements,nodes, vertices, loads, materials, parameters,process_units); break;
     
    4445                case FrictionCoefficientEnum:NodalValuex(responses, FrictionCoefficientEnum,elements,nodes, vertices, loads, materials, parameters,process_units); break;
    4546                default: _error_(" response descriptor \"%s\" not supported yet!",response_descriptor); break;
     47                #else
     48                default: _error_(" ISSM was not compiled with responses capabilities, exiting!");
     49                #endif
    4650        }
    4751
  • issm/trunk/src/c/modules/modules.h

    r9571 r9775  
    8484#include "./Orthx/Orthx.h"
    8585#include "./OutputResultsx/OutputResultsx.h"
    86 #include "./OutputRiftsx/OutputRiftsx.h"
    8786#include "./ConstraintsStatex/ConstraintsStatex.h"
    8887#include "./PointCloudFindNeighborsx/PointCloudFindNeighborsx.h"
  • issm/trunk/src/c/objects/Elements/Element.h

    r9761 r9775  
    6969                virtual void   InputCreate(double scalar,int name,int code)=0;
    7070                virtual void   InputCreate(double* vector, int index,IoModel* iomodel,int M,int N,int vector_type,int vector_enum,int code)=0;
    71                                 virtual void   ProcessResultsUnits(void)=0;
     71                virtual void   ProcessResultsUnits(void)=0;
    7272                virtual void   RequestedOutput(int output_enum,int step,double time)=0;
    7373                virtual void   MinVel(double* pminvel, bool process_units)=0;
  • issm/trunk/src/c/objects/Elements/Penta.cpp

    r9761 r9775  
    524524}
    525525/*}}}*/
    526 /*FUNCTION Penta::CreateDVectorDiagnosticHoriz {{{1*/
    527 ElementVector* Penta::CreateDVectorDiagnosticHoriz(void){
    528 
    529         int approximation;
    530         inputs->GetParameterValue(&approximation,ApproximationEnum);
    531 
    532         switch(approximation){
    533                 case StokesApproximationEnum:
    534                         return CreateDVectorDiagnosticStokes();
    535                 default:
    536                         return NULL; //no need for doftypes outside of stokes approximation
    537         }
    538 }
    539 /*}}}*/
    540 /*FUNCTION Penta::CreateDVectorDiagnosticStokes{{{1*/
    541 ElementVector* Penta::CreateDVectorDiagnosticStokes(void){
    542 
    543         /*output: */
    544         ElementVector* De=NULL;
    545         /*intermediary: */
    546         int approximation;
    547         int i;
    548 
    549         /*Initialize Element vector and return if necessary*/
    550         inputs->GetParameterValue(&approximation,ApproximationEnum);
    551         if(approximation!=StokesApproximationEnum) return NULL;
    552 
    553         De=new ElementVector(nodes,NUMVERTICES,this->parameters,StokesApproximationEnum);
    554 
    555         for (i=0;i<NUMVERTICES;i++){
    556                 De->values[i*4+0]=VelocityEnum;
    557                 De->values[i*4+1]=VelocityEnum;
    558                 De->values[i*4+2]=VelocityEnum;
    559                 De->values[i*4+3]=PressureEnum;
    560         }
    561 
    562         return De;
    563 }
    564 /*}}}*/
    565526/*FUNCTION Penta::CreateKMatrix {{{1*/
    566527void  Penta::CreateKMatrix(Mat Kff, Mat Kfs,Vec df){
     
    581542        /*Just branch to the correct element stiffness matrix generator, according to the type of analysis we are carrying out: */
    582543        switch(analysis_type){
     544                #ifdef _HAVE_DIAGNOSTIC_
    583545                case DiagnosticHorizAnalysisEnum: case AdjointHorizAnalysisEnum:
    584546                        Ke=CreateKMatrixDiagnosticHoriz(); De=CreateDVectorDiagnosticHoriz();
     
    590552                        Ke=CreateKMatrixDiagnosticVert();
    591553                        break;
     554                #endif
    592555                case BedSlopeXAnalysisEnum: case SurfaceSlopeXAnalysisEnum: case BedSlopeYAnalysisEnum: case SurfaceSlopeYAnalysisEnum:
    593556                        Ke=CreateKMatrixSlope();
     
    596559                        Ke=CreateKMatrixPrognostic();
    597560                        break;
     561                #ifdef _HAVE_BALANCED_
    598562                case BalancethicknessAnalysisEnum:
    599563                        Ke=CreateKMatrixBalancethickness();
    600564                        break;
     565                #endif
    601566                #ifdef _HAVE_THERMAL_
    602567                case ThermalAnalysisEnum:
     
    626591}
    627592/*}}}*/
    628 /*FUNCTION Penta::CreateKMatrixBalancethickness {{{1*/
    629 ElementMatrix* Penta::CreateKMatrixBalancethickness(void){
    630 
    631         /*Figure out if this penta is collapsed. If so, then bailout, except if it is at the
    632           bedrock, in which case we spawn a tria element using the 3 first nodes, and use it to build
    633           the stiffness matrix. */
     593/*FUNCTION Penta::CreateKMatrixPrognostic {{{1*/
     594ElementMatrix* Penta::CreateKMatrixPrognostic(void){
     595
    634596        if (!IsOnBed()) return NULL;
    635597
     
    638600        this->InputDepthAverageAtBase(VyEnum,VyAverageEnum);
    639601
    640         /*Spawn Tria element from the base of the Penta: */
    641602        Tria* tria=(Tria*)SpawnTria(0,1,2); //nodes 0, 1 and 2 make the new tria.
    642         ElementMatrix* Ke=tria->CreateKMatrixBalancethickness();
     603        ElementMatrix* Ke=tria->CreateKMatrixPrognostic();
    643604        delete tria->matice; delete tria;
    644605
     
    651612}
    652613/*}}}*/
    653 /*FUNCTION Penta::CreateKMatrixCouplingMacAyealPattyn{{{1*/
    654 ElementMatrix* Penta::CreateKMatrixCouplingMacAyealPattyn(void){
    655        
    656         /*compute all stiffness matrices for this element*/
    657         ElementMatrix* Ke1=CreateKMatrixCouplingMacAyealPattynViscous();
    658         ElementMatrix* Ke2=CreateKMatrixCouplingMacAyealPattynFriction();
    659         ElementMatrix* Ke=new ElementMatrix(Ke1,Ke2);
    660        
    661         /*clean-up and return*/
    662         delete Ke1;
    663         delete Ke2;
    664         return Ke;
    665 }
    666 /*}}}*/
    667 /*FUNCTION Penta::CreateKMatrixCouplingMacAyealPattynViscous{{{1*/
    668 ElementMatrix* Penta::CreateKMatrixCouplingMacAyealPattynViscous(void){
    669 
    670         /*Constants*/
    671         const int    numdofm=NDOF2*NUMVERTICES2D;
    672         const int    numdofp=NDOF2*NUMVERTICES;
    673         const int    numdoftotal=2*NDOF2*NUMVERTICES;
    674 
    675         /*Intermediaries */
    676         int         i,j,ig;
    677         double      Jdet;
    678         double      viscosity,oldviscosity,newviscosity,viscosity_overshoot; //viscosity
    679         double      epsilon[5],oldepsilon[5]; /* epsilon=[exx,eyy,exy,exz,eyz];*/
    680         double      xyz_list[NUMVERTICES][3];
    681         double      B[3][numdofp];
    682         double      Bprime[3][numdofm];
    683         double      D[3][3]={0.0};            // material matrix, simple scalar matrix.
    684         double      D_scalar;
    685         double      Ke_gg[numdofp][numdofm]={0.0}; //local element stiffness matrix
    686         double      Ke_gg_gaussian[numdofp][numdofm]; //stiffness matrix evaluated at the gaussian point.
    687         GaussPenta *gauss=NULL;
    688         GaussTria  *gauss_tria=NULL;
    689 
    690         /*Find penta on bed as pattyn must be coupled to the dofs on the bed: */
    691         Penta* pentabase=GetBasalElement();
    692         Tria* tria=pentabase->SpawnTria(0,1,2); //nodes 0, 1 and 2 make the new tria.
    693 
    694         /*Initialize Element matrix*/
    695         ElementMatrix* Ke1=new ElementMatrix(pentabase->nodes,NUMVERTICES,this->parameters,MacAyealApproximationEnum);
    696         ElementMatrix* Ke2=new ElementMatrix(this->nodes     ,NUMVERTICES,this->parameters,PattynApproximationEnum);
    697         ElementMatrix* Ke =new ElementMatrix(Ke1,Ke2);
    698         delete Ke1; delete Ke2;
    699 
    700         /* Get node coordinates and dof list: */
    701         GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
    702         this->parameters->FindParam(&viscosity_overshoot,DiagnosticViscosityOvershootEnum);
    703         Input* vx_input=inputs->GetInput(VxEnum);       _assert_(vx_input);
    704         Input* vy_input=inputs->GetInput(VyEnum);       _assert_(vy_input);
    705         Input* vxold_input=inputs->GetInput(VxPicardEnum); _assert_(vxold_input);
    706         Input* vyold_input=inputs->GetInput(VyPicardEnum); _assert_(vyold_input);
    707 
    708         /* Start  looping on the number of gaussian points: */
    709         gauss=new GaussPenta(5,5);
    710         gauss_tria=new GaussTria();
    711         for (ig=gauss->begin();ig<gauss->end();ig++){
    712 
    713                 gauss->GaussPoint(ig);
    714                 gauss->SynchronizeGaussTria(gauss_tria);
    715 
    716                 GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss);
    717                 GetBMacAyealPattyn(&B[0][0], &xyz_list[0][0], gauss);
    718                 tria->GetBprimeMacAyeal(&Bprime[0][0], &xyz_list[0][0], gauss_tria);
    719 
    720                 this->GetStrainRate3dPattyn(&epsilon[0],&xyz_list[0][0],gauss,vx_input,vy_input);
    721                 this->GetStrainRate3dPattyn(&oldepsilon[0],&xyz_list[0][0],gauss,vxold_input,vyold_input);
    722                 matice->GetViscosity3d(&viscosity, &epsilon[0]);
    723                 matice->GetViscosity3d(&oldviscosity, &oldepsilon[0]);
    724 
    725                 newviscosity=viscosity+viscosity_overshoot*(viscosity-oldviscosity);
    726                 D_scalar=2*newviscosity*gauss->weight*Jdet;
    727                 for (i=0;i<3;i++) D[i][i]=D_scalar;
    728 
    729                 TripleMultiply( &B[0][0],3,numdofp,1,
    730                                         &D[0][0],3,3,0,
    731                                         &Bprime[0][0],3,numdofm,0,
    732                                         &Ke_gg_gaussian[0][0],0);
    733 
    734                 for( i=0; i<numdofp; i++) for(j=0;j<numdofm; j++) Ke_gg[i][j]+=Ke_gg_gaussian[i][j];
    735         }
    736         for(i=0;i<numdofp;i++) for(j=0;j<numdofm;j++) Ke->values[(i+2*numdofm)*numdoftotal+j]+=Ke_gg[i][j];
    737         for(i=0;i<numdofm;i++) for(j=0;j<numdofp;j++) Ke->values[i*numdoftotal+(j+2*numdofm)]+=Ke_gg[j][i];
    738 
    739         /*Clean-up and return*/
    740         delete tria->matice; delete tria;
    741         delete gauss;
    742         delete gauss_tria;
    743         return Ke;
    744 }
    745 /*}}}*/
    746 /*FUNCTION Penta::CreateKMatrixCouplingMacAyealPattynFriction{{{1*/
    747 ElementMatrix* Penta::CreateKMatrixCouplingMacAyealPattynFriction(void){
    748 
    749         /*Constants*/
    750         const int numdof        = NDOF2 *NUMVERTICES;
    751         const int numdoftotal   = NDOF4 *NUMVERTICES;
    752        
    753         /*Intermediaries */
    754         int       i,j,ig,analysis_type;
    755         double    Jdet2d,slope_magnitude,alpha2;
    756         double    xyz_list[NUMVERTICES][3];
    757         double    xyz_list_tria[NUMVERTICES2D][3]={0.0};
    758         double    slope[3]={0.0,0.0,0.0};
    759         double    MAXSLOPE=.06; // 6 %
    760         double    MOUNTAINKEXPONENT=10;
    761         double    L[2][numdof];
    762         double    DL[2][2]                  ={{ 0,0 },{0,0}}; //for basal drag
    763         double    DL_scalar;
    764         double    Ke_gg[numdof][numdof]     ={0.0};
    765         double    Ke_gg_gaussian[numdof][numdof]; //stiffness matrix contribution from drag
    766         Friction  *friction = NULL;
    767         GaussPenta *gauss=NULL;
    768 
    769         /*Initialize Element matrix and return if necessary*/
    770         if(IsOnShelf() || !IsOnBed()) return NULL;
    771         ElementMatrix* Ke1=new ElementMatrix(nodes,NUMVERTICES,this->parameters,MacAyealApproximationEnum);
    772         ElementMatrix* Ke2=new ElementMatrix(nodes,NUMVERTICES,this->parameters,PattynApproximationEnum);
    773         ElementMatrix* Ke=new ElementMatrix(Ke1,Ke2);
    774         delete Ke1; delete Ke2;
    775 
    776         /*retrieve inputs :*/
    777         GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
    778         for(i=0;i<NUMVERTICES2D;i++) for(j=0;j<2;j++) xyz_list_tria[i][j]=xyz_list[i][j];
    779         parameters->FindParam(&analysis_type,AnalysisTypeEnum);
    780         Input* surface_input=inputs->GetInput(SurfaceEnum); _assert_(surface_input);
    781         Input* vx_input=inputs->GetInput(VxEnum);           _assert_(vx_input);
    782         Input* vy_input=inputs->GetInput(VyEnum);           _assert_(vy_input);
    783         Input* vz_input=inputs->GetInput(VzEnum);           _assert_(vz_input);
    784 
    785         /*build friction object, used later on: */
    786         friction=new Friction("2d",inputs,matpar,analysis_type);
    787 
    788         /* Start  looping on the number of gaussian points: */
    789         gauss=new GaussPenta(0,1,2,2);
    790         for (ig=gauss->begin();ig<gauss->end();ig++){
    791 
    792                 gauss->GaussPoint(ig);
    793 
    794                 /*Friction: */
    795                 friction->GetAlpha2(&alpha2, gauss,VxEnum,VyEnum,VzEnum);
    796 
    797                 // If we have a slope > 6% for this element,  it means  we are on a mountain. In this particular case,
    798                 //velocity should be = 0. To achieve this result, we set alpha2_list to a very high value: */
    799                 surface_input->GetParameterDerivativeValue(&slope[0],&xyz_list[0][0],gauss);
    800                 slope_magnitude=sqrt(pow(slope[0],2)+pow(slope[1],2));
    801 
    802                 if (slope_magnitude>MAXSLOPE){
    803                         alpha2=pow((double)10,MOUNTAINKEXPONENT);
    804                 }
    805 
    806                 GetTriaJacobianDeterminant(&Jdet2d, &xyz_list_tria[0][0],gauss);
    807                 GetL(&L[0][0], gauss,NDOF2);
    808 
    809                 DL_scalar=alpha2*gauss->weight*Jdet2d;
    810                 for (i=0;i<2;i++) DL[i][i]=DL_scalar;
    811                
    812                 /*  Do the triple producte tL*D*L: */
    813                 TripleMultiply( &L[0][0],2,numdof,1,
    814                                         &DL[0][0],2,2,0,
    815                                         &L[0][0],2,numdof,0,
    816                                         &Ke_gg_gaussian[0][0],0);
    817 
    818                 for(i=0;i<numdof;i++) for(j=0;j<numdof;j++) Ke_gg[i][j]+=Ke_gg_gaussian[i][j];
    819         }
    820 
    821         for(i=0;i<numdof;i++) for(j=0;j<numdof;j++) Ke->values[i*numdoftotal+(numdof+j)]+=Ke_gg[i][j];
    822         for(i=0;i<numdof;i++) for(j=0;j<numdof;j++) Ke->values[(i+numdof)*numdoftotal+j]+=Ke_gg[i][j];
    823 
    824         /*Clean up and return*/
    825         delete gauss;
    826         delete friction;
    827         return Ke;
    828 }
    829 /*}}}*/
    830 /*FUNCTION Penta::CreateKMatrixCouplingMacAyealStokes{{{1*/
    831 ElementMatrix* Penta::CreateKMatrixCouplingMacAyealStokes(void){
    832 
    833         /*compute all stiffness matrices for this element*/
    834         ElementMatrix* Ke1=CreateKMatrixCouplingMacAyealStokesViscous();
    835         ElementMatrix* Ke2=CreateKMatrixCouplingMacAyealStokesFriction();
    836         ElementMatrix* Ke =new ElementMatrix(Ke1,Ke2);
    837 
    838         /*clean-up and return*/
    839         delete Ke1;
    840         delete Ke2;
    841         return Ke;
    842 }
    843 /*}}}*/
    844 /*FUNCTION Penta::CreateKMatrixCouplingMacAyealStokesViscous{{{1*/
    845 ElementMatrix* Penta::CreateKMatrixCouplingMacAyealStokesViscous(void){
    846 
    847         /*Constants*/
    848         const int    numdofm=NDOF2*NUMVERTICES2D;
    849         const int    numdofs=NDOF4*NUMVERTICES;
    850         const int    numdoftotal=2*numdofm+numdofs;
    851 
    852         /*Intermediaries */
    853         int         i,j,ig;
    854         double      Jdet;
    855         double      viscosity,stokesreconditioning; //viscosity
    856         double      epsilon[6]; /* epsilon=[exx,eyy,exy,exz,eyz];*/
    857         double      xyz_list[NUMVERTICES][3];
    858         double      B[4][numdofs+3];
    859         double      Bprime[4][numdofm];
    860         double      B2[3][numdofm];
    861         double      Bprime2[3][numdofs+3];
    862         double      D[4][4]={0.0};            // material matrix, simple scalar matrix.
    863         double      D2[3][3]={0.0};            // material matrix, simple scalar matrix.
    864         double      D_scalar;
    865         double      Ke_gg[numdofs][numdofm]={0.0}; //local element stiffness matrix
    866         double      Ke_gg2[numdofm][numdofs]={0.0}; //local element stiffness matrix
    867         double      Ke_gg_gaussian[numdofs+3][numdofm]; //stiffness matrix evaluated at the gaussian point.
    868         double      Ke_gg_gaussian2[numdofm][numdofs+3]; //stiffness matrix evaluated at the gaussian point.
    869         GaussPenta *gauss=NULL;
    870         GaussTria  *gauss_tria=NULL;
    871 
    872         /*Find penta on bed as stokes must be coupled to the dofs on the bed: */
    873         Penta* pentabase=GetBasalElement();
    874         Tria* tria=pentabase->SpawnTria(0,1,2); //nodes 0, 1 and 2 make the new tria.
    875 
    876         /*Initialize Element matrix and return if necessary*/
    877         ElementMatrix* Ke1=new ElementMatrix(pentabase->nodes,NUMVERTICES,this->parameters,MacAyealApproximationEnum);
    878         ElementMatrix* Ke2=new ElementMatrix(this->nodes     ,NUMVERTICES,this->parameters,StokesApproximationEnum);
    879         ElementMatrix* Ke=new ElementMatrix(Ke1,Ke2);
    880         delete Ke1; delete Ke2;
    881 
    882         /* Get node coordinates and dof list: */
    883         GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
    884         parameters->FindParam(&stokesreconditioning,DiagnosticStokesreconditioningEnum);
    885         Input* vx_input=inputs->GetInput(VxEnum);       _assert_(vx_input);
    886         Input* vy_input=inputs->GetInput(VyEnum);       _assert_(vy_input);
    887         Input* vz_input=inputs->GetInput(VzEnum);       _assert_(vz_input);
    888 
    889         /* Start  looping on the number of gaussian points: */
    890         gauss=new GaussPenta(5,5);
    891         gauss_tria=new GaussTria();
    892         for (ig=gauss->begin();ig<gauss->end();ig++){
    893 
    894                 gauss->GaussPoint(ig);
    895                 gauss->SynchronizeGaussTria(gauss_tria);
    896 
    897                 GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss);
    898                 GetBMacAyealStokes(&B[0][0], &xyz_list[0][0], gauss);
    899                 tria->GetBprimeMacAyealStokes(&Bprime[0][0], &xyz_list[0][0], gauss_tria);
    900                 tria->GetBMacAyealStokes(&B2[0][0], &xyz_list[0][0], gauss_tria);
    901                 GetBprimeMacAyealStokes(&Bprime2[0][0], &xyz_list[0][0], gauss);
    902 
    903                 this->GetStrainRate3d(&epsilon[0],&xyz_list[0][0],gauss,vx_input,vy_input,vz_input);
    904                 matice->GetViscosity3dStokes(&viscosity, &epsilon[0]);
    905 
    906                 D_scalar=2*viscosity*gauss->weight*Jdet;
    907                 for (i=0;i<3;i++) D[i][i]=D_scalar;
    908                 D[3][3]=-gauss->weight*Jdet*stokesreconditioning;
    909                 for (i=0;i<3;i++) D2[i][i]=D_scalar;
    910 
    911                 TripleMultiply( &B[0][0],4,numdofs+3,1,
    912                                         &D[0][0],4,4,0,
    913                                         &Bprime[0][0],4,numdofm,0,
    914                                         &Ke_gg_gaussian[0][0],0);
    915 
    916                 TripleMultiply( &B2[0][0],3,numdofm,1,
    917                                         &D2[0][0],3,3,0,
    918                                         &Bprime2[0][0],3,numdofs+3,0,
    919                                         &Ke_gg_gaussian2[0][0],0);
    920 
    921                 for( i=0; i<numdofs; i++) for(j=0;j<numdofm; j++) Ke_gg[i][j]+=Ke_gg_gaussian[i][j];
    922                 for( i=0; i<numdofm; i++) for(j=0;j<numdofs; j++) Ke_gg2[i][j]+=Ke_gg_gaussian2[i][j];
    923         }
    924         for(i=0;i<numdofs;i++) for(j=0;j<numdofm;j++) Ke->values[(i+2*numdofm)*numdoftotal+j]+=Ke_gg[i][j];
    925         for(i=0;i<numdofm;i++) for(j=0;j<numdofs;j++) Ke->values[i*numdoftotal+(j+2*numdofm)]+=Ke_gg2[i][j];
    926 
    927         /*Clean-up and return*/
    928         delete tria->matice; delete tria;
    929         delete gauss;
    930         delete gauss_tria;
    931         return Ke;
    932 }
    933 /*}}}*/
    934 /*FUNCTION Penta::CreateKMatrixCouplingMacAyealStokesFriction {{{1*/
    935 ElementMatrix* Penta::CreateKMatrixCouplingMacAyealStokesFriction(void){
    936 
    937         /*Constants*/
    938         const int numdof=NUMVERTICES*NDOF4;
    939         const int numdofm=NUMVERTICES*NDOF2;
    940         const int numdof2d=NUMVERTICES2D*NDOF4;
    941         const int numdof2dm=NUMVERTICES2D*NDOF2;
    942         const int numdoftot=numdof+numdofm;
    943 
    944         /*Intermediaries */
    945         int        i,j,ig;
    946         int        analysis_type,approximation;
    947         double     stokesreconditioning;
    948         double     viscosity,alpha2_gauss,Jdet2d;
    949         double    bed_normal[3];
    950         double     epsilon[6]; /* epsilon=[exx,eyy,ezz,exy,exz,eyz];*/
    951         double     xyz_list[NUMVERTICES][3];
    952         double    xyz_list_tria[NUMVERTICES2D][3];
    953         double     LMacAyealStokes[8][numdof2dm];
    954         double     LprimeMacAyealStokes[8][numdof2d];
    955         double     DLMacAyealStokes[8][8]={0.0};
    956         double     LStokesMacAyeal[4][numdof2d];
    957         double     LprimeStokesMacAyeal[4][numdof2dm];
    958         double     DLStokesMacAyeal[4][4]={0.0};
    959         double     Ke_drag_gaussian[numdof2dm][numdof2d];
    960         double     Ke_drag_gaussian2[numdof2d][numdof2dm];
    961         Friction*  friction=NULL;
    962         GaussPenta *gauss=NULL;
    963 
    964         /*If on water or not Stokes, skip stiffness: */
    965         inputs->GetParameterValue(&approximation,ApproximationEnum);
    966         if(IsOnShelf() || !IsOnBed()) return NULL;
    967         ElementMatrix* Ke1=new ElementMatrix(this->nodes,NUMVERTICES,this->parameters,MacAyealApproximationEnum);
    968         ElementMatrix* Ke2=new ElementMatrix(this->nodes,NUMVERTICES,this->parameters,StokesApproximationEnum);
    969         ElementMatrix* Ke=new ElementMatrix(Ke1,Ke2);
    970         delete Ke1; delete Ke2;
    971 
    972         /*Retrieve all inputs and parameters*/
    973         GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
    974         parameters->FindParam(&analysis_type,AnalysisTypeEnum);
    975         parameters->FindParam(&stokesreconditioning,DiagnosticStokesreconditioningEnum);
    976         Input* vx_input=inputs->GetInput(VxEnum); _assert_(vx_input);
    977         Input* vy_input=inputs->GetInput(VyEnum); _assert_(vy_input);
    978         Input* vz_input=inputs->GetInput(VzEnum); _assert_(vz_input);
    979         for(i=0;i<NUMVERTICES2D;i++) for(j=0;j<3;j++) xyz_list_tria[i][j]=xyz_list[i][j];
    980 
    981         /*build friction object, used later on: */
    982         friction=new Friction("3d",inputs,matpar,analysis_type);
    983 
    984         /* Start  looping on the number of gaussian points: */
    985         gauss=new GaussPenta(0,1,2,2);
    986         for (ig=gauss->begin();ig<gauss->end();ig++){
    987 
    988                 gauss->GaussPoint(ig);
    989 
    990                 GetTriaJacobianDeterminant(&Jdet2d, &xyz_list_tria[0][0],gauss);
    991                 GetLMacAyealStokes(&LMacAyealStokes[0][0], gauss);
    992                 GetLprimeMacAyealStokes(&LprimeMacAyealStokes[0][0], &xyz_list[0][0], gauss);
    993                 GetLStokesMacAyeal(&LStokesMacAyeal[0][0], gauss);
    994                 GetLprimeStokesMacAyeal(&LprimeStokesMacAyeal[0][0], &xyz_list[0][0], gauss);
    995 
    996                 this->GetStrainRate3d(&epsilon[0],&xyz_list[0][0],gauss,vx_input,vy_input,vz_input);
    997                 matice->GetViscosity3dStokes(&viscosity,&epsilon[0]);
    998 
    999                 BedNormal(&bed_normal[0],xyz_list_tria);
    1000                 friction->GetAlpha2(&alpha2_gauss, gauss,VxEnum,VyEnum,VzEnum);
    1001 
    1002                 DLMacAyealStokes[0][0]=alpha2_gauss*gauss->weight*Jdet2d;
    1003                 DLMacAyealStokes[1][1]=alpha2_gauss*gauss->weight*Jdet2d;
    1004                 DLMacAyealStokes[2][2]=-alpha2_gauss*gauss->weight*Jdet2d*bed_normal[0]*bed_normal[2];
    1005                 DLMacAyealStokes[3][3]=-alpha2_gauss*gauss->weight*Jdet2d*bed_normal[1]*bed_normal[2];
    1006                 DLMacAyealStokes[4][4]=-2*viscosity*gauss->weight*Jdet2d*bed_normal[0];
    1007                 DLMacAyealStokes[5][5]=-2*viscosity*gauss->weight*Jdet2d*bed_normal[1];
    1008                 DLMacAyealStokes[6][6]=stokesreconditioning*gauss->weight*Jdet2d*bed_normal[0];
    1009                 DLMacAyealStokes[7][7]=stokesreconditioning*gauss->weight*Jdet2d*bed_normal[1];
    1010 
    1011                 DLStokesMacAyeal[0][0]=alpha2_gauss*gauss->weight*Jdet2d;
    1012                 DLStokesMacAyeal[1][1]=alpha2_gauss*gauss->weight*Jdet2d;
    1013                 DLStokesMacAyeal[2][2]=-alpha2_gauss*gauss->weight*Jdet2d*bed_normal[0]*bed_normal[2];
    1014                 DLStokesMacAyeal[3][3]=-alpha2_gauss*gauss->weight*Jdet2d*bed_normal[1]*bed_normal[2];
    1015                
    1016                 TripleMultiply( &LMacAyealStokes[0][0],8,numdof2dm,1,
    1017                                         &DLMacAyealStokes[0][0],8,8,0,
    1018                                         &LprimeMacAyealStokes[0][0],8,numdof2d,0,
    1019                                         &Ke_drag_gaussian[0][0],0);
    1020 
    1021                 TripleMultiply( &LStokesMacAyeal[0][0],4,numdof2d,1,
    1022                                         &DLStokesMacAyeal[0][0],4,4,0,
    1023                                         &LprimeStokesMacAyeal[0][0],4,numdof2dm,0,
    1024                                         &Ke_drag_gaussian2[0][0],0);
    1025 
    1026                 for(i=0;i<numdof2dm;i++) for(j=0;j<numdof2d;j++) Ke->values[i*numdoftot+j+numdofm]+=Ke_drag_gaussian[i][j];
    1027                 for(i=0;i<numdof2d;i++) for(j=0;j<numdof2dm;j++) Ke->values[(i+numdofm)*numdoftot+j]+=Ke_drag_gaussian2[i][j];
    1028         }
    1029 
    1030         /*Clean up and return*/
    1031         delete gauss;
    1032         delete friction;
    1033         return Ke;
    1034 }
    1035 /*}}}*/
    1036 /*FUNCTION Penta::CreateKMatrixCouplingPattynStokes{{{1*/
    1037 ElementMatrix* Penta::CreateKMatrixCouplingPattynStokes(void){
    1038 
    1039         /*compute all stiffness matrices for this element*/
    1040         ElementMatrix* Ke1=new ElementMatrix(this->nodes,NUMVERTICES,this->parameters,PattynApproximationEnum);
    1041         ElementMatrix* Ke2=new ElementMatrix(this->nodes,NUMVERTICES,this->parameters,StokesApproximationEnum);
    1042         ElementMatrix* Ke=new ElementMatrix(Ke1,Ke2);
    1043         delete Ke1;
    1044         delete Ke2;
    1045         Ke1=CreateKMatrixDiagnosticPattyn();
    1046         Ke2=CreateKMatrixDiagnosticStokes();
    1047 
    1048         /*Constants*/
    1049         const int    numdofp=NDOF2*NUMVERTICES;
    1050         const int    numdofs=NDOF4*NUMVERTICES;
    1051         const int    numdoftotal=(NDOF2+NDOF4)*NUMVERTICES;
    1052         int          i,j;
    1053 
    1054         for(i=0;i<numdofs;i++) for(j=0;j<NUMVERTICES;j++){
    1055                 Ke->values[(i+numdofp)*numdoftotal+NDOF2*j+0]+=Ke2->values[i*numdofs+NDOF4*j+0];
    1056                 Ke->values[(i+numdofp)*numdoftotal+NDOF2*j+1]+=Ke2->values[i*numdofs+NDOF4*j+1];
    1057         }
    1058         for(i=0;i<numdofp;i++) for(j=0;j<NUMVERTICES;j++){
    1059                 Ke->values[i*numdoftotal+numdofp+NDOF4*j+0]+=Ke1->values[i*numdofp+NDOF2*j+0];
    1060                 Ke->values[i*numdoftotal+numdofp+NDOF4*j+1]+=Ke1->values[i*numdofp+NDOF2*j+1];
    1061         }
    1062 
    1063         /*clean-up and return*/
    1064         delete Ke1;
    1065         delete Ke2;
    1066         return Ke;
    1067 }
    1068 /*}}}*/
    1069 /*FUNCTION Penta::CreateKMatrixDiagnosticHoriz {{{1*/
    1070 ElementMatrix* Penta::CreateKMatrixDiagnosticHoriz(void){
    1071 
    1072         int approximation;
    1073         inputs->GetParameterValue(&approximation,ApproximationEnum);
    1074 
    1075         switch(approximation){
    1076                 case MacAyealApproximationEnum:
    1077                         return CreateKMatrixDiagnosticMacAyeal2d();
    1078                 case PattynApproximationEnum:
    1079                         return CreateKMatrixDiagnosticPattyn();
    1080                 case StokesApproximationEnum:
    1081                         return CreateKMatrixDiagnosticStokes();
    1082                 case HutterApproximationEnum:
    1083                         return NULL;
    1084                 case NoneApproximationEnum:
    1085                         return NULL;
    1086                 case MacAyealPattynApproximationEnum:
    1087                         return CreateKMatrixDiagnosticMacAyealPattyn();
    1088                 case MacAyealStokesApproximationEnum:
    1089                         return CreateKMatrixDiagnosticMacAyealStokes();
    1090                 case PattynStokesApproximationEnum:
    1091                         return CreateKMatrixDiagnosticPattynStokes();
    1092                 default:
    1093                         _error_("Approximation %s not supported yet",EnumToStringx(approximation));
    1094         }
    1095 }
    1096 /*}}}*/
    1097 /*FUNCTION Penta::CreateKMatrixDiagnosticHutter{{{1*/
    1098 ElementMatrix* Penta::CreateKMatrixDiagnosticHutter(void){
    1099 
    1100         /*Constants*/
    1101         const int numdof=NDOF2*NUMVERTICES;
    1102 
    1103         /*Intermediaries*/
    1104         int       connectivity[2];
    1105         int       i,i0,i1,j0,j1;
    1106         double    one0,one1;
    1107 
    1108         /*Initialize Element matrix*/
    1109         ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,NoneApproximationEnum);
    1110 
    1111         /*Spawn 3 beam elements: */
    1112         for(i=0;i<3;i++){
    1113                 /*2 dofs of first node*/
    1114                 i0=2*i;
    1115                 i1=2*i+1;
    1116                 /*2 dofs of second node*/
    1117                 j0=2*(i+3);
    1118                 j1=2*(i+3)+1;
    1119 
    1120                 /*Find connectivity for the two nodes*/
    1121                 connectivity[0]=nodes[i]->GetConnectivity();
    1122                 connectivity[1]=nodes[i+3]->GetConnectivity();
    1123                 one0=1/(double)connectivity[0];
    1124                 one1=1/(double)connectivity[1];
    1125 
    1126                 /*Create matrix for these two nodes*/
    1127                 if (IsOnBed() && IsOnSurface()){
    1128                         Ke->values[i0*numdof+i0]=one0;
    1129                         Ke->values[i1*numdof+i1]=one0;
    1130                         Ke->values[j0*numdof+i0]=-one1;
    1131                         Ke->values[j0*numdof+j0]=one1;
    1132                         Ke->values[j1*numdof+i1]=-one1;
    1133                         Ke->values[j1*numdof+j1]=one1;
    1134                 }
    1135                 else if (IsOnBed()){
    1136                         Ke->values[i0*numdof+i0]=one0;
    1137                         Ke->values[i1*numdof+i1]=one0;
    1138                         Ke->values[j0*numdof+i0]=-2*one1;
    1139                         Ke->values[j0*numdof+j0]=2*one1;
    1140                         Ke->values[j1*numdof+i1]=-2*one1;
    1141                         Ke->values[j1*numdof+j1]=2*one1;
    1142                 }
    1143                 else if (IsOnSurface()){
    1144                         Ke->values[j0*numdof+i0]=-one1;
    1145                         Ke->values[j0*numdof+j0]=one1;
    1146                         Ke->values[j1*numdof+i1]=-one1;
    1147                         Ke->values[j1*numdof+j1]=one1;
    1148                 }
    1149                 else{ //node is on two horizontal layers and beams include the values only once, so the have to use half of the connectivity
    1150                         Ke->values[j0*numdof+i0]=-2*one1;
    1151                         Ke->values[j0*numdof+j0]=2*one1;
    1152                         Ke->values[j1*numdof+i1]=-2*one1;
    1153                         Ke->values[j1*numdof+j1]=2*one1;
    1154                 }
    1155         }
    1156 
    1157         /*Clean up and return*/
    1158         return Ke;
    1159 }
    1160 /*FUNCTION Penta::CreateKMatrixDiagnosticMacAyeal2d{{{1*/
    1161 ElementMatrix* Penta::CreateKMatrixDiagnosticMacAyeal2d(void){
    1162 
    1163         /*Figure out if this penta is collapsed. If so, then bailout, except if it is at the
    1164           bedrock, in which case we spawn a tria element using the 3 first nodes, and use it to build
    1165           the stiffness matrix. */
    1166         if (!IsOnBed()) return NULL;
    1167 
    1168         /*Depth Averaging B*/
    1169         this->InputDepthAverageAtBase(MaterialsRheologyBEnum,MaterialsRheologyBbarEnum,MaterialsEnum);
    1170 
    1171         /*Call Tria function*/
    1172         Tria* tria=(Tria*)SpawnTria(0,1,2); //nodes 0, 1 and 2 make the new tria.
    1173         ElementMatrix* Ke=tria->CreateKMatrixDiagnosticMacAyeal();
    1174         delete tria->matice; delete tria;
    1175 
    1176         /*Delete B averaged*/
    1177         this->matice->inputs->DeleteInput(MaterialsRheologyBbarEnum);
    1178 
    1179         /*clean up and return*/
    1180         return Ke;
    1181 }
    1182 /*}}}*/
    1183 /*FUNCTION Penta::CreateKMatrixDiagnosticMacAyeal3d{{{1*/
    1184 ElementMatrix* Penta::CreateKMatrixDiagnosticMacAyeal3d(void){
    1185 
    1186         /*compute all stiffness matrices for this element*/
    1187         ElementMatrix* Ke1=CreateKMatrixDiagnosticMacAyeal3dViscous();
    1188         ElementMatrix* Ke2=CreateKMatrixDiagnosticMacAyeal3dFriction();
    1189         ElementMatrix* Ke =new ElementMatrix(Ke1,Ke2);
    1190 
    1191         /*clean-up and return*/
    1192         delete Ke1;
    1193         delete Ke2;
    1194         return Ke;
    1195 }
    1196 /*}}}*/
    1197 /*FUNCTION Penta::CreateKMatrixDiagnosticMacAyeal3dViscous{{{1*/
    1198 ElementMatrix* Penta::CreateKMatrixDiagnosticMacAyeal3dViscous(void){
    1199 
    1200         /*Constants*/
    1201         const int    numdof2d=2*NUMVERTICES2D;
    1202 
    1203         /*Intermediaries */
    1204         int         i,j,ig,approximation;
    1205         double      Jdet;
    1206         double      viscosity, oldviscosity, newviscosity, viscosity_overshoot;
    1207         double      epsilon[5],oldepsilon[5]; /* epsilon=[exx,eyy,exy,exz,eyz];*/
    1208         double      epsilons[6]; //6 for stokes
    1209         double      xyz_list[NUMVERTICES][3];
    1210         double      B[3][numdof2d];
    1211         double      Bprime[3][numdof2d];
    1212         double      D[3][3]={0.0};            // material matrix, simple scalar matrix.
    1213         double      D_scalar;
    1214         double      Ke_gg_gaussian[numdof2d][numdof2d]; //stiffness matrix evaluated at the gaussian point.
    1215         Tria*       tria=NULL;
    1216         Penta*      pentabase=NULL;
    1217         GaussPenta *gauss=NULL;
    1218         GaussTria  *gauss_tria=NULL;
    1219 
    1220         /*Find penta on bed as this is a macayeal elements: */
    1221         pentabase=GetBasalElement();
    1222         tria=pentabase->SpawnTria(0,1,2); //nodes 0, 1 and 2 make the new tria.
    1223 
    1224         /*Initialize Element matrix*/
    1225         ElementMatrix* Ke=new ElementMatrix(tria->nodes,NUMVERTICES2D,this->parameters,MacAyealApproximationEnum);
    1226         inputs->GetParameterValue(&approximation,ApproximationEnum);
    1227 
    1228         /*Retrieve all inputs and parameters*/
    1229         GetVerticesCoordinates(&xyz_list[0][0], nodes,NUMVERTICES);
    1230         this->parameters->FindParam(&viscosity_overshoot,DiagnosticViscosityOvershootEnum);
    1231         Input* vx_input=inputs->GetInput(VxEnum);       _assert_(vx_input);
    1232         Input* vy_input=inputs->GetInput(VyEnum);       _assert_(vy_input);
    1233         Input* vxold_input=inputs->GetInput(VxPicardEnum); _assert_(vxold_input);
    1234         Input* vyold_input=inputs->GetInput(VyPicardEnum); _assert_(vyold_input);
    1235         Input* vz_input=inputs->GetInput(VzEnum);       _assert_(vz_input);
    1236 
    1237         /* Start  looping on the number of gaussian points: */
    1238         gauss=new GaussPenta(5,5);
    1239         gauss_tria=new GaussTria();
    1240         for (ig=gauss->begin();ig<gauss->end();ig++){
    1241 
    1242                 gauss->GaussPoint(ig);
    1243                 gauss->SynchronizeGaussTria(gauss_tria);
    1244 
    1245                 GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss);
    1246                 tria->GetBMacAyeal(&B[0][0], &xyz_list[0][0], gauss_tria);
    1247                 tria->GetBprimeMacAyeal(&Bprime[0][0], &xyz_list[0][0], gauss_tria);
    1248 
    1249                 if(approximation==MacAyealPattynApproximationEnum){
    1250                         this->GetStrainRate3dPattyn(&epsilon[0],&xyz_list[0][0],gauss,vx_input,vy_input);
    1251                         this->GetStrainRate3dPattyn(&oldepsilon[0],&xyz_list[0][0],gauss,vxold_input,vyold_input);
    1252                         matice->GetViscosity3d(&viscosity, &epsilon[0]);
    1253                         matice->GetViscosity3d(&oldviscosity, &oldepsilon[0]);
    1254 
    1255                         newviscosity=viscosity+viscosity_overshoot*(viscosity-oldviscosity);
    1256                 }
    1257                 else if (approximation==MacAyealStokesApproximationEnum){
    1258                         this->GetStrainRate3d(&epsilons[0],&xyz_list[0][0],gauss,vx_input,vy_input,vz_input);
    1259                         matice->GetViscosity3dStokes(&newviscosity,&epsilons[0]);
    1260                 }
    1261                 else _error_("approximation %i (%s) not supported yet",approximation,EnumToStringx(approximation));
    1262 
    1263                 D_scalar=2*newviscosity*gauss->weight*Jdet;
    1264                 for (i=0;i<3;i++) D[i][i]=D_scalar;
    1265 
    1266                 TripleMultiply( &B[0][0],3,numdof2d,1,
    1267                                         &D[0][0],3,3,0,
    1268                                         &Bprime[0][0],3,numdof2d,0,
    1269                                         &Ke_gg_gaussian[0][0],0);
    1270 
    1271                 for(i=0;i<numdof2d;i++) for(j=0;j<numdof2d;j++) Ke->values[i*numdof2d+j]+=Ke_gg_gaussian[i][j];
    1272         }
    1273 
    1274         /*Clean up and return*/
    1275         delete tria->matice;
    1276         delete tria;
    1277         delete gauss_tria;
    1278         delete gauss;
    1279         return Ke;
    1280 }
    1281 /*}}}*/
    1282 /*FUNCTION Penta::CreateKMatrixDiagnosticMacAyeal3dFriction{{{1*/
    1283 ElementMatrix* Penta::CreateKMatrixDiagnosticMacAyeal3dFriction(void){
    1284 
    1285         /*Initialize Element matrix and return if necessary*/
    1286         if(IsOnShelf() || !IsOnBed()) return NULL;
    1287 
    1288         /*Build a tria element using the 3 nodes of the base of the penta. Then use
    1289          * the tria functionality to build a friction stiffness matrix on these 3
    1290          * nodes: */
    1291         Tria* tria=(Tria*)SpawnTria(0,1,2); //nodes 0, 1 and 2 make the new tria.
    1292         ElementMatrix* Ke=tria->CreateKMatrixDiagnosticMacAyealFriction();
    1293         delete tria->matice; delete tria;
    1294 
    1295         /*clean-up and return*/
    1296         return Ke;
    1297 }
    1298 /*}}}*/
    1299 /*FUNCTION Penta::CreateKMatrixDiagnosticMacAyealPattyn{{{1*/
    1300 ElementMatrix* Penta::CreateKMatrixDiagnosticMacAyealPattyn(void){
    1301 
    1302         /*compute all stiffness matrices for this element*/
    1303         ElementMatrix* Ke1=CreateKMatrixDiagnosticMacAyeal3d();
    1304         ElementMatrix* Ke2=CreateKMatrixDiagnosticPattyn();
    1305         ElementMatrix* Ke3=CreateKMatrixCouplingMacAyealPattyn();
    1306         ElementMatrix* Ke =new ElementMatrix(Ke1,Ke2,Ke3);
    1307 
    1308         /*clean-up and return*/
    1309         delete Ke1;
    1310         delete Ke2;
    1311         delete Ke3;
    1312         return Ke;
    1313 }
    1314 /*}}}*/
    1315 /*FUNCTION Penta::CreateKMatrixDiagnosticMacAyealStokes{{{1*/
    1316 ElementMatrix* Penta::CreateKMatrixDiagnosticMacAyealStokes(void){
    1317 
    1318         /*compute all stiffness matrices for this element*/
    1319         ElementMatrix* Ke1=CreateKMatrixDiagnosticMacAyeal3d();
    1320         ElementMatrix* Ke2=CreateKMatrixDiagnosticStokes();
    1321         ElementMatrix* Ke3=CreateKMatrixCouplingMacAyealStokes();
    1322         ElementMatrix* Ke =new ElementMatrix(Ke1,Ke2,Ke3);
    1323 
    1324         /*clean-up and return*/
    1325         delete Ke1;
    1326         delete Ke2;
    1327         delete Ke3;
    1328         return Ke;
    1329 }
    1330 /*}}}*/
    1331 /*FUNCTION Penta::CreateKMatrixDiagnosticPattyn{{{1*/
    1332 ElementMatrix* Penta::CreateKMatrixDiagnosticPattyn(void){
    1333 
    1334         /*compute all stiffness matrices for this element*/
    1335         ElementMatrix* Ke1=CreateKMatrixDiagnosticPattynViscous();
    1336         ElementMatrix* Ke2=CreateKMatrixDiagnosticPattynFriction();
    1337         ElementMatrix* Ke =new ElementMatrix(Ke1,Ke2);
    1338 
    1339         /*clean-up and return*/
    1340         delete Ke1;
    1341         delete Ke2;
    1342         return Ke;
    1343 
    1344 }
    1345 /*}}}*/
    1346 /*FUNCTION Penta::CreateKMatrixDiagnosticPattynViscous{{{1*/
    1347 ElementMatrix* Penta::CreateKMatrixDiagnosticPattynViscous(void){
    1348 
    1349         /*Constants*/
    1350         const int    numdof=NDOF2*NUMVERTICES;
    1351 
    1352         /*Intermediaries */
    1353         int        i,j,ig;
    1354         int        approximation;
    1355         double     xyz_list[NUMVERTICES][3];
    1356         double     Jdet;
    1357         double     viscosity,oldviscosity,newviscosity,viscosity_overshoot; //viscosity
    1358         double     epsilon[5],oldepsilon[5]; /* epsilon=[exx,eyy,exy,exz,eyz];*/
    1359         double     D_scalar;
    1360         double     D[5][5]={0.0};            // material matrix, simple scalar matrix.
    1361         double     B[5][numdof];
    1362         double     Bprime[5][numdof];
    1363         Tria*      tria=NULL;
    1364         GaussPenta *gauss=NULL;
    1365 
    1366         /*Initialize Element matrix*/
    1367         ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,PattynApproximationEnum);
    1368 
    1369         /*Retrieve all inputs and parameters*/
    1370         inputs->GetParameterValue(&approximation,ApproximationEnum);
    1371         GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
    1372         this->parameters->FindParam(&viscosity_overshoot,DiagnosticViscosityOvershootEnum);
    1373         Input* vx_input=inputs->GetInput(VxEnum);       _assert_(vx_input);
    1374         Input* vy_input=inputs->GetInput(VyEnum);       _assert_(vy_input);
    1375         Input* vxold_input=inputs->GetInput(VxPicardEnum); _assert_(vxold_input);
    1376         Input* vyold_input=inputs->GetInput(VyPicardEnum); _assert_(vyold_input);
    1377 
    1378         /* Start  looping on the number of gaussian points: */
    1379         gauss=new GaussPenta(5,5);
    1380         for (ig=gauss->begin();ig<gauss->end();ig++){
    1381 
    1382                 gauss->GaussPoint(ig);
    1383 
    1384                 GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss);
    1385                 GetBPattyn(&B[0][0], &xyz_list[0][0], gauss);
    1386                 GetBprimePattyn(&Bprime[0][0], &xyz_list[0][0], gauss);
    1387 
    1388                 this->GetStrainRate3dPattyn(&epsilon[0],&xyz_list[0][0],gauss,vx_input,vy_input);
    1389                 this->GetStrainRate3dPattyn(&oldepsilon[0],&xyz_list[0][0],gauss,vxold_input,vyold_input);
    1390                 matice->GetViscosity3d(&viscosity, &epsilon[0]);
    1391                 matice->GetViscosity3d(&oldviscosity, &oldepsilon[0]);
    1392                 newviscosity=viscosity+viscosity_overshoot*(viscosity-oldviscosity);
    1393 
    1394                 D_scalar=2*newviscosity*gauss->weight*Jdet;
    1395                 for (i=0;i<5;i++) D[i][i]=D_scalar;
    1396 
    1397                 TripleMultiply( &B[0][0],5,numdof,1,
    1398                                         &D[0][0],5,5,0,
    1399                                         &Bprime[0][0],5,numdof,0,
    1400                                         &Ke->values[0],1);
    1401         }
    1402 
    1403         /*Clean up and return*/
    1404         delete gauss;
    1405         return Ke;
    1406 }
    1407 /*}}}*/
    1408 /*FUNCTION Penta::CreateKMatrixDiagnosticPattynFriction{{{1*/
    1409 ElementMatrix* Penta::CreateKMatrixDiagnosticPattynFriction(void){
    1410 
    1411         /*Constants*/
    1412         const int numdof   = NDOF2*NUMVERTICES;
    1413        
    1414         /*Intermediaries */
    1415         int       i,j,ig;
    1416         int       analysis_type;
    1417         double    xyz_list[NUMVERTICES][3];
    1418         double    xyz_list_tria[NUMVERTICES2D][3]={0.0};
    1419         double    slope_magnitude,alpha2,Jdet;
    1420         double    slope[3]={0.0,0.0,0.0};
    1421         double    MAXSLOPE=.06; // 6 %
    1422         double    MOUNTAINKEXPONENT=10;
    1423         double    L[2][numdof];
    1424         double    DL[2][2]={{ 0,0 },{0,0}}; //for basal drag
    1425         double    DL_scalar;
    1426         Friction  *friction = NULL;
    1427         GaussPenta *gauss=NULL;
    1428 
    1429         /*Initialize Element matrix and return if necessary*/
    1430         if(IsOnShelf() || !IsOnBed()) return NULL;
    1431 
    1432         ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,PattynApproximationEnum);
    1433 
    1434         /*Retrieve all inputs and parameters*/
    1435         GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
    1436         for(i=0;i<NUMVERTICES2D;i++) for(j=0;j<2;j++) xyz_list_tria[i][j]=xyz_list[i][j];
    1437         parameters->FindParam(&analysis_type,AnalysisTypeEnum);
    1438         Input* surface_input=inputs->GetInput(SurfaceEnum); _assert_(surface_input);
    1439         Input* vx_input=inputs->GetInput(VxEnum);           _assert_(vx_input);
    1440         Input* vy_input=inputs->GetInput(VyEnum);           _assert_(vy_input);
    1441         Input* vz_input=inputs->GetInput(VzEnum);           _assert_(vz_input);
    1442 
    1443         /*build friction object, used later on: */
    1444         friction=new Friction("2d",inputs,matpar,analysis_type);
    1445 
    1446         /* Start  looping on the number of gaussian points: */
    1447         gauss=new GaussPenta(0,1,2,2);
    1448         for (ig=gauss->begin();ig<gauss->end();ig++){
    1449 
    1450                 gauss->GaussPoint(ig);
    1451 
    1452                 GetTriaJacobianDeterminant(&Jdet, &xyz_list_tria[0][0],gauss);
    1453                 GetL(&L[0][0], gauss,NDOF2);
    1454 
    1455                 surface_input->GetParameterDerivativeValue(&slope[0],&xyz_list[0][0],gauss);
    1456                 friction->GetAlpha2(&alpha2, gauss,VxEnum,VyEnum,VzEnum);
    1457                 slope_magnitude=sqrt(pow(slope[0],2)+pow(slope[1],2));
    1458 
    1459                 // If we have a slope > 6% for this element,  it means  we are on a mountain. In this particular case,
    1460                 //velocity should be = 0. To achieve this result, we set alpha2_list to a very high value: */
    1461                 if (slope_magnitude>MAXSLOPE){
    1462                         alpha2=pow((double)10,MOUNTAINKEXPONENT);
    1463                 }
    1464                
    1465                 DL_scalar=alpha2*gauss->weight*Jdet;
    1466                 for (i=0;i<2;i++) DL[i][i]=DL_scalar;
    1467                
    1468                 TripleMultiply( &L[0][0],2,numdof,1,
    1469                                         &DL[0][0],2,2,0,
    1470                                         &L[0][0],2,numdof,0,
    1471                                         &Ke->values[0],1);
    1472         }
    1473 
    1474         /*Clean up and return*/
    1475         delete gauss;
    1476         delete friction;
    1477         return Ke;
    1478 }
    1479 /*}}}*/
    1480 /*FUNCTION Penta::CreateKMatrixDiagnosticPattynStokes{{{1*/
    1481 ElementMatrix* Penta::CreateKMatrixDiagnosticPattynStokes(void){
    1482 
    1483         /*compute all stiffness matrices for this element*/
    1484         ElementMatrix* Ke1=CreateKMatrixDiagnosticPattyn();
    1485         ElementMatrix* Ke2=CreateKMatrixDiagnosticStokes();
    1486         ElementMatrix* Ke3=CreateKMatrixCouplingPattynStokes();
    1487         ElementMatrix* Ke =new ElementMatrix(Ke1,Ke2,Ke3);
    1488 
    1489         /*clean-up and return*/
    1490         delete Ke1;
    1491         delete Ke2;
    1492         delete Ke3;
    1493         return Ke;
    1494 }
    1495 /*}}}*/
    1496 /*FUNCTION Penta::CreateKMatrixDiagnosticStokes{{{1*/
    1497 ElementMatrix* Penta::CreateKMatrixDiagnosticStokes(void){
    1498 
    1499         /*compute all stiffness matrices for this element*/
    1500         ElementMatrix* Ke1=CreateKMatrixDiagnosticStokesViscous();
    1501         ElementMatrix* Ke2=CreateKMatrixDiagnosticStokesFriction();
    1502         ElementMatrix* Ke =new ElementMatrix(Ke1,Ke2);
    1503 
    1504         /*clean-up and return*/
    1505         delete Ke1;
    1506         delete Ke2;
    1507         return Ke;
    1508 }
    1509 /*}}}*/
    1510 /*FUNCTION Penta::CreateKMatrixDiagnosticStokesViscous {{{1*/
    1511 ElementMatrix* Penta::CreateKMatrixDiagnosticStokesViscous(void){
    1512 
    1513         /*Intermediaries */
    1514         int        i,j,ig,approximation;
    1515         double     Jdet,viscosity,stokesreconditioning;
    1516         double     xyz_list[NUMVERTICES][3];
    1517         double     epsilon[6]; /* epsilon=[exx,eyy,ezz,exy,exz,eyz];*/
    1518         double     B[8][27];
    1519         double     B_prime[8][27];
    1520         double     D_scalar;
    1521         double     D[8][8]={0.0};
    1522         double     Ke_temp[27][27]={0.0}; //for the six nodes and the bubble
    1523         double     Ke_gaussian[27][27];
    1524         GaussPenta *gauss=NULL;
    1525 
    1526         /*If on water or not Stokes, skip stiffness: */
    1527         inputs->GetParameterValue(&approximation,ApproximationEnum);
    1528         if(approximation!=StokesApproximationEnum && approximation!=MacAyealStokesApproximationEnum && approximation!=PattynStokesApproximationEnum) return NULL;
    1529         ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,StokesApproximationEnum);
    1530 
    1531         /*Retrieve all inputs and parameters*/
    1532         GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
    1533         parameters->FindParam(&stokesreconditioning,DiagnosticStokesreconditioningEnum);
    1534         Input* vx_input=inputs->GetInput(VxEnum); _assert_(vx_input);
    1535         Input* vy_input=inputs->GetInput(VyEnum); _assert_(vy_input);
    1536         Input* vz_input=inputs->GetInput(VzEnum); _assert_(vz_input);
    1537 
    1538         /* Start  looping on the number of gaussian points: */
    1539         gauss=new GaussPenta(5,5);
    1540         for (ig=gauss->begin();ig<gauss->end();ig++){
    1541 
    1542                 gauss->GaussPoint(ig);
    1543 
    1544                 GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss);
    1545                 GetBStokes(&B[0][0],&xyz_list[0][0],gauss);
    1546                 GetBprimeStokes(&B_prime[0][0],&xyz_list[0][0],gauss);
    1547 
    1548                 this->GetStrainRate3d(&epsilon[0],&xyz_list[0][0],gauss,vx_input,vy_input,vz_input);
    1549                 matice->GetViscosity3dStokes(&viscosity,&epsilon[0]);
    1550 
    1551                 D_scalar=gauss->weight*Jdet;
    1552                 for (i=0;i<6;i++) D[i][i]=D_scalar*2*viscosity;
    1553                 for (i=6;i<8;i++) D[i][i]=-D_scalar*stokesreconditioning;
    1554 
    1555                 TripleMultiply( &B[0][0],8,27,1,
    1556                                         &D[0][0],8,8,0,
    1557                                         &B_prime[0][0],8,27,0,
    1558                                         &Ke_gaussian[0][0],0);
    1559 
    1560                 for(i=0;i<27;i++) for(j=0;j<27;j++) Ke_temp[i][j]+=Ke_gaussian[i][j];
    1561         }
    1562 
    1563         /*Condensation*/
    1564         ReduceMatrixStokes(Ke->values, &Ke_temp[0][0]);
    1565 
    1566         /*Clean up and return*/
    1567         delete gauss;
    1568         return Ke;
    1569 }
    1570 /*}}}*/
    1571 /*FUNCTION Penta::CreateKMatrixDiagnosticStokesFriction {{{1*/
    1572 ElementMatrix* Penta::CreateKMatrixDiagnosticStokesFriction(void){
    1573 
    1574         /*Constants*/
    1575         const int numdof=NUMVERTICES*NDOF4;
    1576         const int numdof2d=NUMVERTICES2D*NDOF4;
    1577 
    1578         /*Intermediaries */
    1579         int        i,j,ig;
    1580         int        analysis_type,approximation;
    1581         double     stokesreconditioning;
    1582         double     viscosity,alpha2_gauss,Jdet2d;
    1583         double    bed_normal[3];
    1584         double     epsilon[6]; /* epsilon=[exx,eyy,ezz,exy,exz,eyz];*/
    1585         double     xyz_list[NUMVERTICES][3];
    1586         double    xyz_list_tria[NUMVERTICES2D][3];
    1587         double     LStokes[14][numdof2d];
    1588         double     LprimeStokes[14][numdof2d];
    1589         double     DLStokes[14][14]={0.0};
    1590         double     Ke_drag_gaussian[numdof2d][numdof2d];
    1591         Friction*  friction=NULL;
    1592         GaussPenta *gauss=NULL;
    1593 
    1594         /*If on water or not Stokes, skip stiffness: */
    1595         inputs->GetParameterValue(&approximation,ApproximationEnum);
    1596         if(IsOnShelf() || !IsOnBed() || (approximation!=StokesApproximationEnum && approximation!=MacAyealStokesApproximationEnum &&  approximation!=PattynStokesApproximationEnum)) return NULL;
    1597         ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,StokesApproximationEnum);
    1598 
    1599         /*Retrieve all inputs and parameters*/
    1600         GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
    1601         parameters->FindParam(&analysis_type,AnalysisTypeEnum);
    1602         parameters->FindParam(&stokesreconditioning,DiagnosticStokesreconditioningEnum);
    1603         Input* vx_input=inputs->GetInput(VxEnum); _assert_(vx_input);
    1604         Input* vy_input=inputs->GetInput(VyEnum); _assert_(vy_input);
    1605         Input* vz_input=inputs->GetInput(VzEnum); _assert_(vz_input);
    1606         for(i=0;i<NUMVERTICES2D;i++) for(j=0;j<3;j++) xyz_list_tria[i][j]=xyz_list[i][j];
    1607 
    1608         /*build friction object, used later on: */
    1609         friction=new Friction("3d",inputs,matpar,analysis_type);
    1610 
    1611         /* Start  looping on the number of gaussian points: */
    1612         gauss=new GaussPenta(0,1,2,2);
    1613         for (ig=gauss->begin();ig<gauss->end();ig++){
    1614 
    1615                 gauss->GaussPoint(ig);
    1616 
    1617                 GetTriaJacobianDeterminant(&Jdet2d, &xyz_list_tria[0][0],gauss);
    1618                 GetLStokes(&LStokes[0][0], gauss);
    1619                 GetLprimeStokes(&LprimeStokes[0][0], &xyz_list[0][0], gauss);
    1620 
    1621                 this->GetStrainRate3d(&epsilon[0],&xyz_list[0][0],gauss,vx_input,vy_input,vz_input);
    1622                 matice->GetViscosity3dStokes(&viscosity,&epsilon[0]);
    1623 
    1624                 BedNormal(&bed_normal[0],xyz_list_tria);
    1625                 friction->GetAlpha2(&alpha2_gauss, gauss,VxEnum,VyEnum,VzEnum);
    1626 
    1627                 DLStokes[0][0]=alpha2_gauss*gauss->weight*Jdet2d;
    1628                 DLStokes[1][1]=alpha2_gauss*gauss->weight*Jdet2d;
    1629                 DLStokes[2][2]=-alpha2_gauss*gauss->weight*Jdet2d*bed_normal[0]*bed_normal[2];
    1630                 DLStokes[3][3]=-alpha2_gauss*gauss->weight*Jdet2d*bed_normal[1]*bed_normal[2];
    1631                 DLStokes[4][4]=-alpha2_gauss*gauss->weight*Jdet2d*bed_normal[0]*bed_normal[2];
    1632                 DLStokes[5][5]=-alpha2_gauss*gauss->weight*Jdet2d*bed_normal[1]*bed_normal[2];
    1633                 DLStokes[6][6]=-2*viscosity*gauss->weight*Jdet2d*bed_normal[0];
    1634                 DLStokes[7][7]=-2*viscosity*gauss->weight*Jdet2d*bed_normal[1];
    1635                 DLStokes[8][8]=-2*viscosity*gauss->weight*Jdet2d*bed_normal[2];
    1636                 DLStokes[9][9]=-2*viscosity*gauss->weight*Jdet2d*bed_normal[0]/2.0;
    1637                 DLStokes[10][10]=-2*viscosity*gauss->weight*Jdet2d*bed_normal[1]/2.0;
    1638                 DLStokes[11][11]=stokesreconditioning*gauss->weight*Jdet2d*bed_normal[0];
    1639                 DLStokes[12][12]=stokesreconditioning*gauss->weight*Jdet2d*bed_normal[1];
    1640                 DLStokes[13][13]=stokesreconditioning*gauss->weight*Jdet2d*bed_normal[2];
    1641 
    1642                 TripleMultiply( &LStokes[0][0],14,numdof2d,1,
    1643                                         &DLStokes[0][0],14,14,0,
    1644                                         &LprimeStokes[0][0],14,numdof2d,0,
    1645                                         &Ke_drag_gaussian[0][0],0);
    1646 
    1647                 for(i=0;i<numdof2d;i++) for(j=0;j<numdof2d;j++) Ke->values[i*numdof+j]+=Ke_drag_gaussian[i][j];
    1648         }
    1649 
    1650         /*Clean up and return*/
    1651         delete gauss;
    1652         delete friction;
    1653         return Ke;
    1654 }
    1655 /*}}}*/
    1656 /*FUNCTION Penta::CreateKMatrixDiagnosticVert {{{1*/
    1657 ElementMatrix* Penta::CreateKMatrixDiagnosticVert(void){
    1658        
    1659         /*compute all stiffness matrices for this element*/
    1660         ElementMatrix* Ke1=CreateKMatrixDiagnosticVertVolume();
    1661         ElementMatrix* Ke2=CreateKMatrixDiagnosticVertSurface();
    1662         ElementMatrix* Ke =new ElementMatrix(Ke1,Ke2);
    1663 
    1664         /*clean-up and return*/
    1665         delete Ke1;
    1666         delete Ke2;
    1667         return Ke;
    1668 
    1669 }
    1670 /*}}}*/
    1671 /*FUNCTION Penta::CreateKMatrixDiagnosticVertVolume {{{1*/
    1672 ElementMatrix* Penta::CreateKMatrixDiagnosticVertVolume(void){
    1673 
    1674         /*Constants*/
    1675         const int    numdof=NDOF1*NUMVERTICES;
    1676 
    1677         /*Intermediaries */
    1678         int         i,j,ig;
    1679         double      Jdet;
    1680         double      xyz_list[NUMVERTICES][3];
    1681         double      B[NDOF1][NUMVERTICES];
    1682         double      Bprime[NDOF1][NUMVERTICES];
    1683         double      DL_scalar;
    1684         GaussPenta  *gauss=NULL;
    1685 
    1686         /*Initialize Element matrix*/
    1687         ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,NoneApproximationEnum);
    1688 
    1689         /*Retrieve all inputs and parameters*/
    1690         GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
    1691 
    1692         /* Start  looping on the number of gaussian points: */
    1693         gauss=new GaussPenta(2,2);
    1694         for (ig=gauss->begin();ig<gauss->end();ig++){
    1695 
    1696                 gauss->GaussPoint(ig);
    1697 
    1698                 GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss);
    1699                 GetBVert(&B[0][0], &xyz_list[0][0], gauss);
    1700                 GetBprimeVert(&Bprime[0][0], &xyz_list[0][0], gauss);
    1701 
    1702                 DL_scalar=gauss->weight*Jdet;
    1703 
    1704                 TripleMultiply( &B[0][0],1,NUMVERTICES,1,
    1705                                         &DL_scalar,1,1,0,
    1706                                         &Bprime[0][0],1,NUMVERTICES,0,
    1707                                         &Ke->values[0],1);
    1708         }
    1709 
    1710         /*Clean up and return*/
    1711         delete gauss;
    1712         return Ke;
    1713 }
    1714 /*}}}*/
    1715 /*FUNCTION Penta::CreateKMatrixDiagnosticVertSurface {{{1*/
    1716 ElementMatrix* Penta::CreateKMatrixDiagnosticVertSurface(void){
    1717 
    1718         if (!IsOnSurface()) return NULL;
    1719 
    1720         /*Constants*/
    1721         const int numdof=NDOF1*NUMVERTICES;
    1722 
    1723         /*Intermediaries */
    1724         int       i,j,ig;
    1725         double    xyz_list[NUMVERTICES][3];
    1726         double    xyz_list_tria[NUMVERTICES2D][3];
    1727         double    surface_normal[3];
    1728         double    Jdet2d,DL_scalar;
    1729         double    basis[NUMVERTICES];
    1730         GaussPenta *gauss=NULL;
    1731 
    1732         /*Initialize Element matrix*/
    1733         ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,NoneApproximationEnum);
    1734 
    1735         /*Retrieve all inputs and parameters*/
    1736         GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
    1737         for(i=0;i<NUMVERTICES2D;i++) for(j=0;j<3;j++) xyz_list_tria[i][j]=xyz_list[i+3][j];
    1738         SurfaceNormal(&surface_normal[0],xyz_list_tria);
    1739 
    1740         /* Start  looping on the number of gaussian points: */
    1741         gauss=new GaussPenta(3,4,5,2);
    1742         for (ig=gauss->begin();ig<gauss->end();ig++){
    1743 
    1744                 gauss->GaussPoint(ig);
    1745 
    1746                 GetTriaJacobianDeterminant(&Jdet2d, &xyz_list_tria[0][0],gauss);
    1747                 GetNodalFunctionsP1(&basis[0], gauss);
    1748 
    1749                 DL_scalar= - gauss->weight*Jdet2d*surface_normal[2];
    1750 
    1751                 TripleMultiply( basis,1,numdof,1,
    1752                                         &DL_scalar,1,1,0,
    1753                                         basis,1,numdof,0,
    1754                                         &Ke->values[0],1);
    1755         }
    1756 
    1757         /*Clean up and return*/
    1758         delete gauss;
    1759         return Ke;
    1760 }
    1761 /*}}}*/
    1762 /*FUNCTION Penta::CreateKMatrixPrognostic {{{1*/
    1763 ElementMatrix* Penta::CreateKMatrixPrognostic(void){
    1764 
    1765         if (!IsOnBed()) return NULL;
    1766 
    1767         /*Depth Averaging Vx and Vy*/
    1768         this->InputDepthAverageAtBase(VxEnum,VxAverageEnum);
    1769         this->InputDepthAverageAtBase(VyEnum,VyAverageEnum);
    1770 
    1771         Tria* tria=(Tria*)SpawnTria(0,1,2); //nodes 0, 1 and 2 make the new tria.
    1772         ElementMatrix* Ke=tria->CreateKMatrixPrognostic();
    1773         delete tria->matice; delete tria;
    1774 
    1775         /*Delete Vx and Vy averaged*/
    1776         this->inputs->DeleteInput(VxAverageEnum);
    1777         this->inputs->DeleteInput(VyAverageEnum);
    1778 
    1779         /*clean up and return*/
    1780         return Ke;
    1781 }
    1782 /*}}}*/
    1783614/*FUNCTION Penta::CreateKMatrixSlope {{{1*/
    1784615ElementMatrix* Penta::CreateKMatrixSlope(void){
     
    1794625}
    1795626/*}}}*/
    1796 
    1797 #ifdef _HAVE_THERMAL_
    1798 /*FUNCTION Penta::CreateKMatrixEnthalpy {{{1*/
    1799 ElementMatrix* Penta::CreateKMatrixEnthalpy(void){
    1800        
    1801         /*compute all stiffness matrices for this element*/
    1802         ElementMatrix* Ke1=CreateKMatrixEnthalpyVolume();
    1803         ElementMatrix* Ke2=CreateKMatrixEnthalpyShelf();
    1804         ElementMatrix* Ke =new ElementMatrix(Ke1,Ke2);
    1805        
    1806         /*clean-up and return*/
    1807         delete Ke1;
    1808         delete Ke2;
    1809         return Ke;
    1810 }
    1811 /*}}}*/
    1812 /*FUNCTION Penta::CreateKMatrixEnthalpyVolume {{{1*/
    1813 ElementMatrix* Penta::CreateKMatrixEnthalpyVolume(void){
    1814 
    1815         /*Constants*/
    1816         const int    numdof=NDOF1*NUMVERTICES;
    1817 
    1818         /*Intermediaries */
    1819         int        stabilization;
    1820         int        i,j,ig,found=0;
    1821         double     Jdet,u,v,w,um,vm,wm;
    1822         double     gravity,rho_ice,rho_water;
    1823         double     epsvel=2.220446049250313e-16;
    1824         double     heatcapacity,thermalconductivity,dt;
    1825         double     pressure,enthalpy;
    1826         double     latentheat,kappa;
    1827         double     tau_parameter,diameter;
    1828         double     xyz_list[NUMVERTICES][3];
    1829         double     B[3][numdof];
    1830         double     Bprime[3][numdof];
    1831         double     B_conduct[3][numdof];
    1832         double     B_advec[3][numdof];
    1833         double     B_stab[2][numdof];
    1834         double     Bprime_advec[3][numdof];
    1835         double     L[numdof];
    1836         double     dbasis[3][6];
    1837         double     D_scalar_conduct,D_scalar_advec;
    1838         double     D_scalar_trans,D_scalar_stab;
    1839         double     D[3][3];
    1840         double     K[2][2]={0.0};
    1841         Tria*      tria=NULL;
    1842         GaussPenta *gauss=NULL;
    1843 
    1844         /*Initialize Element matrix*/
    1845         ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,NoneApproximationEnum);
    1846 
    1847         /*Retrieve all inputs and parameters*/
    1848         GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
    1849         rho_water=matpar->GetRhoWater();
    1850         rho_ice=matpar->GetRhoIce();
    1851         gravity=matpar->GetG();
    1852         heatcapacity=matpar->GetHeatCapacity();
    1853         latentheat=matpar->GetLatentHeat();
    1854         thermalconductivity=matpar->GetThermalConductivity();
    1855         this->parameters->FindParam(&dt,TimesteppingTimeStepEnum);
    1856         this->parameters->FindParam(&stabilization,ThermalStabilizationEnum);
    1857         Input* pressure_input=inputs->GetInput(PressureEnum);      _assert_(pressure_input);
    1858         Input* enthalpy_input=inputs->GetInput(EnthalpyEnum);      _assert_(enthalpy_input);
    1859         Input* vx_input=inputs->GetInput(VxEnum);                  _assert_(vx_input);
    1860         Input* vy_input=inputs->GetInput(VyEnum);                  _assert_(vy_input);
    1861         Input* vz_input=inputs->GetInput(VzEnum);                  _assert_(vz_input);
    1862         Input* vxm_input=inputs->GetInput(VxMeshEnum);             _assert_(vxm_input);
    1863         Input* vym_input=inputs->GetInput(VyMeshEnum);             _assert_(vym_input);
    1864         Input* vzm_input=inputs->GetInput(VzMeshEnum);             _assert_(vzm_input);
    1865         if (stabilization==2) diameter=MinEdgeLength(xyz_list);
    1866 
    1867         /* Start  looping on the number of gaussian points: */
    1868         gauss=new GaussPenta(2,2);
    1869         for (ig=gauss->begin();ig<gauss->end();ig++){
    1870 
    1871                 gauss->GaussPoint(ig);
    1872 
    1873                 GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss);
    1874 
    1875                 /*Conduction: */ 
    1876                 /*Need to change that depending on enthalpy value -> cold or temperate ice: */ 
    1877 
    1878                 GetBConduct(&B_conduct[0][0],&xyz_list[0][0],gauss);
    1879 
    1880                 enthalpy_input->GetParameterValue(&enthalpy, gauss);
    1881                 pressure_input->GetParameterValue(&pressure, gauss);
    1882                 kappa=matpar->GetEnthalpyDiffusionParameter(enthalpy,pressure);
    1883                 D_scalar_conduct=gauss->weight*Jdet*kappa;
    1884                 if(dt) D_scalar_conduct=D_scalar_conduct*dt;
    1885 
    1886                 D[0][0]=D_scalar_conduct; D[0][1]=0; D[0][2]=0;
    1887                 D[1][0]=0; D[1][1]=D_scalar_conduct; D[1][2]=0;
    1888                 D[2][0]=0; D[2][1]=0; D[2][2]=D_scalar_conduct;
    1889 
    1890                 TripleMultiply(&B_conduct[0][0],3,numdof,1,
    1891                                         &D[0][0],3,3,0,
    1892                                         &B_conduct[0][0],3,numdof,0,
    1893                                         &Ke->values[0],1);
    1894 
    1895                 /*Advection: */
    1896 
    1897                 GetBAdvec(&B_advec[0][0],&xyz_list[0][0],gauss);
    1898                 GetBprimeAdvec(&Bprime_advec[0][0],&xyz_list[0][0],gauss);
    1899 
    1900                 vx_input->GetParameterValue(&u, gauss);
    1901                 vy_input->GetParameterValue(&v, gauss);
    1902                 vz_input->GetParameterValue(&w, gauss);
    1903                 vxm_input->GetParameterValue(&um,gauss);
    1904                 vym_input->GetParameterValue(&vm,gauss);
    1905                 vzm_input->GetParameterValue(&wm,gauss);
    1906 
    1907                 D_scalar_advec=gauss->weight*Jdet;
    1908                 if(dt) D_scalar_advec=D_scalar_advec*dt;
    1909 
    1910                 D[0][0]=D_scalar_advec*(u-um);D[0][1]=0;                    D[0][2]=0;
    1911                 D[1][0]=0;                    D[1][1]=D_scalar_advec*(v-vm);D[1][2]=0;
    1912                 D[2][0]=0;                    D[2][1]=0;                    D[2][2]=D_scalar_advec*(w-wm);
    1913 
    1914                 TripleMultiply(&B_advec[0][0],3,numdof,1,
    1915                                         &D[0][0],3,3,0,
    1916                                         &Bprime_advec[0][0],3,numdof,0,
    1917                                         &Ke->values[0],1);
    1918 
    1919                 /*Transient: */
    1920 
    1921                 if(dt){
    1922                         GetNodalFunctionsP1(&L[0], gauss);
    1923                         D_scalar_trans=gauss->weight*Jdet;
    1924                         D_scalar_trans=D_scalar_trans;
    1925 
    1926                         TripleMultiply(&L[0],numdof,1,0,
    1927                                                 &D_scalar_trans,1,1,0,
    1928                                                 &L[0],1,numdof,0,
    1929                                                 &Ke->values[0],1);
    1930                 }
    1931 
    1932                 /*Artifficial diffusivity*/
    1933 
    1934                 if(stabilization==1){
    1935                         /*Build K: */
    1936                         D_scalar_stab=gauss->weight*Jdet/(pow(u-um,2)+pow(v-vm,2)+epsvel);
    1937                         if(dt) D_scalar_stab=D_scalar_stab*dt;
    1938                         K[0][0]=D_scalar_stab*pow(u,2);       K[0][1]=D_scalar_stab*fabs(u)*fabs(v);
    1939                         K[1][0]=D_scalar_stab*fabs(u)*fabs(v);K[1][1]=D_scalar_stab*pow(v,2);
    1940 
    1941                         GetBArtdiff(&B_stab[0][0],&xyz_list[0][0],gauss);
    1942 
    1943                         TripleMultiply(&B_stab[0][0],2,numdof,1,
    1944                                                 &K[0][0],2,2,0,
    1945                                                 &B_stab[0][0],2,numdof,0,
    1946                                                 &Ke->values[0],1);
    1947                 }
    1948                 else if(stabilization==2){
    1949 
    1950                         GetNodalFunctionsP1Derivatives(&dbasis[0][0],&xyz_list[0][0], gauss);
    1951 
    1952                         tau_parameter=GetStabilizationParameter(u-um,v-vm,w-wm,diameter,rho_ice,heatcapacity,thermalconductivity);
    1953 
    1954                         for(i=0;i<numdof;i++){
    1955                                 for(j=0;j<numdof;j++){
    1956                                         Ke->values[i*numdof+j]+=tau_parameter*D_scalar_advec*
    1957                                           ((u-um)*dbasis[0][i]+(v-vm)*dbasis[1][i]+(w-wm)*dbasis[2][i])*((u-um)*dbasis[0][j]+(v-vm)*dbasis[1][j]+(w-wm)*dbasis[2][j]);
    1958                                 }
    1959                         }
    1960                         if(dt){
    1961                                 for(i=0;i<numdof;i++){
    1962                                         for(j=0;j<numdof;j++){
    1963                                                 Ke->values[i*numdof+j]+=tau_parameter*D_scalar_trans*L[j]*((u-um)*dbasis[0][i]+(v-vm)*dbasis[1][i]+(w-wm)*dbasis[2][i]);
    1964                                         }
    1965                                 }
    1966                         }
    1967                 }
    1968         }
    1969 
    1970         /*Clean up and return*/
    1971         delete gauss;
    1972         return Ke;
    1973 }
    1974 /*}}}*/
    1975 /*FUNCTION Penta::CreateKMatrixEnthalpyShelf {{{1*/
    1976 ElementMatrix* Penta::CreateKMatrixEnthalpyShelf(void){
    1977 
    1978         /*Constants*/
    1979         const int    numdof=NDOF1*NUMVERTICES;
    1980 
    1981         /*Intermediaries */
    1982         int       i,j,ig;
    1983         double    mixed_layer_capacity,thermal_exchange_velocity;
    1984         double    rho_ice,rho_water,heatcapacity;
    1985         double    Jdet2d,dt;
    1986         double    xyz_list[NUMVERTICES][3];
    1987         double   xyz_list_tria[NUMVERTICES2D][3];
    1988         double    basis[NUMVERTICES];
    1989         double    D_scalar;
    1990         GaussPenta *gauss=NULL;
    1991 
    1992         /*Initialize Element matrix and return if necessary*/
    1993         if (!IsOnBed() || !IsOnShelf()) return NULL;
    1994         ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,NoneApproximationEnum);
    1995 
    1996         /*Retrieve all inputs and parameters*/
    1997         this->parameters->FindParam(&dt,TimesteppingTimeStepEnum);
    1998         mixed_layer_capacity=matpar->GetMixedLayerCapacity();
    1999         thermal_exchange_velocity=matpar->GetThermalExchangeVelocity();
    2000         rho_water=matpar->GetRhoWater();
    2001         rho_ice=matpar->GetRhoIce();
    2002         heatcapacity=matpar->GetHeatCapacity();
    2003         GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
    2004         for(i=0;i<NUMVERTICES2D;i++) for(j=0;j<3;j++) xyz_list_tria[i][j]=xyz_list[i][j];
    2005 
    2006         /* Start looping on the number of gauss (nodes on the bedrock) */
    2007         gauss=new GaussPenta(0,1,2,2);
    2008         for (ig=gauss->begin();ig<gauss->end();ig++){
    2009 
    2010                 gauss->GaussPoint(ig);
    2011                
    2012                 GetTriaJacobianDeterminant(&Jdet2d, &xyz_list_tria[0][0], gauss);
    2013                 GetNodalFunctionsP1(&basis[0], gauss);
    2014                                
    2015                 D_scalar=gauss->weight*Jdet2d*rho_water*mixed_layer_capacity*thermal_exchange_velocity/(rho_ice*heatcapacity);
    2016                 if(dt) D_scalar=dt*D_scalar;
    2017 
    2018                 TripleMultiply(&basis[0],numdof,1,0,
    2019                                         &D_scalar,1,1,0,
    2020                                         &basis[0],1,numdof,0,
    2021                                         &Ke->values[0],1);
    2022         }
    2023        
    2024         /*Clean up and return*/
    2025         delete gauss;
    2026         return Ke;
    2027 }
    2028 /*}}}*/
    2029 /*FUNCTION Penta::CreateKMatrixMelting {{{1*/
    2030 ElementMatrix* Penta::CreateKMatrixMelting(void){
    2031 
    2032         if (!IsOnBed()) return NULL;
    2033 
    2034         Tria* tria=(Tria*)SpawnTria(0,1,2); //nodes 0, 1 and 2 make the new tria.
    2035         ElementMatrix* Ke=tria->CreateKMatrixMelting();
    2036 
    2037         delete tria->matice; delete tria;
    2038         return Ke;
    2039 }
    2040 /*}}}*/
    2041 /*FUNCTION Penta::CreateKMatrixThermal {{{1*/
    2042 ElementMatrix* Penta::CreateKMatrixThermal(void){
    2043        
    2044         /*compute all stiffness matrices for this element*/
    2045         ElementMatrix* Ke1=CreateKMatrixThermalVolume();
    2046         ElementMatrix* Ke2=CreateKMatrixThermalShelf();
    2047         ElementMatrix* Ke =new ElementMatrix(Ke1,Ke2);
    2048        
    2049         /*clean-up and return*/
    2050         delete Ke1;
    2051         delete Ke2;
    2052         return Ke;
    2053 }
    2054 /*}}}*/
    2055 /*FUNCTION Penta::CreateKMatrixThermalVolume {{{1*/
    2056 ElementMatrix* Penta::CreateKMatrixThermalVolume(void){
    2057 
    2058         /*Constants*/
    2059         const int    numdof=NDOF1*NUMVERTICES;
    2060 
    2061         /*Intermediaries */
    2062         int        stabilization;
    2063         int        i,j,ig,found=0;
    2064         double     Jdet,u,v,w,um,vm,wm;
    2065         double     epsvel=2.220446049250313e-16;
    2066         double     gravity,rho_ice,rho_water;
    2067         double     heatcapacity,thermalconductivity,dt;
    2068         double     tau_parameter,diameter;
    2069         double     xyz_list[NUMVERTICES][3];
    2070         double     B[3][numdof];
    2071         double     Bprime[3][numdof];
    2072         double     B_conduct[3][numdof];
    2073         double     B_advec[3][numdof];
    2074         double     B_stab[2][numdof];
    2075         double     Bprime_advec[3][numdof];
    2076         double     L[numdof];
    2077         double     dbasis[3][6];
    2078         double     D_scalar_conduct,D_scalar_advec;
    2079         double     D_scalar_trans,D_scalar_stab;
    2080         double     D[3][3];
    2081         double     K[2][2]={0.0};
    2082         Tria*      tria=NULL;
    2083         GaussPenta *gauss=NULL;
    2084 
    2085         /*Initialize Element matrix*/
    2086         ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,NoneApproximationEnum);
    2087 
    2088         /*Retrieve all inputs and parameters*/
    2089         GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
    2090         rho_water=matpar->GetRhoWater();
    2091         rho_ice=matpar->GetRhoIce();
    2092         gravity=matpar->GetG();
    2093         heatcapacity=matpar->GetHeatCapacity();
    2094         thermalconductivity=matpar->GetThermalConductivity();
    2095         this->parameters->FindParam(&dt,TimesteppingTimeStepEnum);
    2096         this->parameters->FindParam(&stabilization,ThermalStabilizationEnum);
    2097         Input* vx_input=inputs->GetInput(VxEnum);      _assert_(vx_input);
    2098         Input* vy_input=inputs->GetInput(VyEnum);      _assert_(vy_input);
    2099         Input* vz_input=inputs->GetInput(VzEnum);      _assert_(vz_input);
    2100         Input* vxm_input=inputs->GetInput(VxMeshEnum); _assert_(vxm_input);
    2101         Input* vym_input=inputs->GetInput(VyMeshEnum); _assert_(vym_input);
    2102         Input* vzm_input=inputs->GetInput(VzMeshEnum); _assert_(vzm_input);
    2103         if (stabilization==2) diameter=MinEdgeLength(xyz_list);
    2104 
    2105         /* Start  looping on the number of gaussian points: */
    2106         gauss=new GaussPenta(2,2);
    2107         for (ig=gauss->begin();ig<gauss->end();ig++){
    2108 
    2109                 gauss->GaussPoint(ig);
    2110 
    2111                 GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss);
    2112 
    2113                 /*Conduction: */
    2114 
    2115                 GetBConduct(&B_conduct[0][0],&xyz_list[0][0],gauss);
    2116 
    2117                 D_scalar_conduct=gauss->weight*Jdet*(thermalconductivity/(rho_ice*heatcapacity));
    2118                 if(dt) D_scalar_conduct=D_scalar_conduct*dt;
    2119 
    2120                 D[0][0]=D_scalar_conduct; D[0][1]=0; D[0][2]=0;
    2121                 D[1][0]=0; D[1][1]=D_scalar_conduct; D[1][2]=0;
    2122                 D[2][0]=0; D[2][1]=0; D[2][2]=D_scalar_conduct;
    2123 
    2124                 TripleMultiply(&B_conduct[0][0],3,numdof,1,
    2125                                         &D[0][0],3,3,0,
    2126                                         &B_conduct[0][0],3,numdof,0,
    2127                                         &Ke->values[0],1);
    2128 
    2129                 /*Advection: */
    2130 
    2131                 GetBAdvec(&B_advec[0][0],&xyz_list[0][0],gauss);
    2132                 GetBprimeAdvec(&Bprime_advec[0][0],&xyz_list[0][0],gauss);
    2133 
    2134                 vx_input->GetParameterValue(&u, gauss);
    2135                 vy_input->GetParameterValue(&v, gauss);
    2136                 vz_input->GetParameterValue(&w, gauss);
    2137                 vxm_input->GetParameterValue(&um,gauss);
    2138                 vym_input->GetParameterValue(&vm,gauss);
    2139                 vzm_input->GetParameterValue(&wm,gauss);
    2140 
    2141                 D_scalar_advec=gauss->weight*Jdet;
    2142                 if(dt) D_scalar_advec=D_scalar_advec*dt;
    2143 
    2144                 D[0][0]=D_scalar_advec*(u-um);D[0][1]=0;                    D[0][2]=0;
    2145                 D[1][0]=0;                    D[1][1]=D_scalar_advec*(v-vm);D[1][2]=0;
    2146                 D[2][0]=0;                    D[2][1]=0;                    D[2][2]=D_scalar_advec*(w-wm);
    2147 
    2148                 TripleMultiply(&B_advec[0][0],3,numdof,1,
    2149                                         &D[0][0],3,3,0,
    2150                                         &Bprime_advec[0][0],3,numdof,0,
    2151                                         &Ke->values[0],1);
    2152 
    2153                 /*Transient: */
    2154 
    2155                 if(dt){
    2156                         GetNodalFunctionsP1(&L[0], gauss);
    2157                         D_scalar_trans=gauss->weight*Jdet;
    2158                         D_scalar_trans=D_scalar_trans;
    2159 
    2160                         TripleMultiply(&L[0],numdof,1,0,
    2161                                                 &D_scalar_trans,1,1,0,
    2162                                                 &L[0],1,numdof,0,
    2163                                                 &Ke->values[0],1);
    2164                 }
    2165 
    2166                 /*Artifficial diffusivity*/
    2167 
    2168                 if(stabilization==1){
    2169                         /*Build K: */
    2170                         D_scalar_stab=gauss->weight*Jdet/(pow(u-um,2)+pow(v-vm,2)+epsvel);
    2171                         if(dt) D_scalar_stab=D_scalar_stab*dt;
    2172                         K[0][0]=D_scalar_stab*pow(u,2);       K[0][1]=D_scalar_stab*fabs(u)*fabs(v);
    2173                         K[1][0]=D_scalar_stab*fabs(u)*fabs(v);K[1][1]=D_scalar_stab*pow(v,2);
    2174 
    2175                         GetBArtdiff(&B_stab[0][0],&xyz_list[0][0],gauss);
    2176 
    2177                         TripleMultiply(&B_stab[0][0],2,numdof,1,
    2178                                                 &K[0][0],2,2,0,
    2179                                                 &B_stab[0][0],2,numdof,0,
    2180                                                 &Ke->values[0],1);
    2181                 }
    2182                 else if(stabilization==2){
    2183 
    2184                         GetNodalFunctionsP1Derivatives(&dbasis[0][0],&xyz_list[0][0], gauss);
    2185 
    2186                         tau_parameter=GetStabilizationParameter(u-um,v-vm,w-wm,diameter,rho_ice,heatcapacity,thermalconductivity);
    2187 
    2188                         for(i=0;i<numdof;i++){
    2189                                 for(j=0;j<numdof;j++){
    2190                                         Ke->values[i*numdof+j]+=tau_parameter*D_scalar_advec*
    2191                                           ((u-um)*dbasis[0][i]+(v-vm)*dbasis[1][i]+(w-wm)*dbasis[2][i])*((u-um)*dbasis[0][j]+(v-vm)*dbasis[1][j]+(w-wm)*dbasis[2][j]);
    2192                                 }
    2193                         }
    2194                         if(dt){
    2195                                 for(i=0;i<numdof;i++){
    2196                                         for(j=0;j<numdof;j++){
    2197                                                 Ke->values[i*numdof+j]+=tau_parameter*D_scalar_trans*L[j]*((u-um)*dbasis[0][i]+(v-vm)*dbasis[1][i]+(w-wm)*dbasis[2][i]);
    2198                                         }
    2199                                 }
    2200                         }
    2201                 }
    2202         }
    2203 
    2204         /*Clean up and return*/
    2205         delete gauss;
    2206         return Ke;
    2207 }
    2208 /*}}}*/
    2209 /*FUNCTION Penta::CreateKMatrixThermalShelf {{{1*/
    2210 ElementMatrix* Penta::CreateKMatrixThermalShelf(void){
    2211 
    2212 
    2213         /*Constants*/
    2214         const int    numdof=NDOF1*NUMVERTICES;
    2215 
    2216         /*Intermediaries */
    2217         int       i,j,ig;
    2218         double    mixed_layer_capacity,thermal_exchange_velocity;
    2219         double    rho_ice,rho_water,heatcapacity;
    2220         double    Jdet2d,dt;
    2221         double    xyz_list[NUMVERTICES][3];
    2222         double   xyz_list_tria[NUMVERTICES2D][3];
    2223         double    basis[NUMVERTICES];
    2224         double    D_scalar;
    2225         GaussPenta *gauss=NULL;
    2226 
    2227         /*Initialize Element matrix and return if necessary*/
    2228         if (!IsOnBed() || !IsOnShelf()) return NULL;
    2229         ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,NoneApproximationEnum);
    2230 
    2231         /*Retrieve all inputs and parameters*/
    2232         this->parameters->FindParam(&dt,TimesteppingTimeStepEnum);
    2233         mixed_layer_capacity=matpar->GetMixedLayerCapacity();
    2234         thermal_exchange_velocity=matpar->GetThermalExchangeVelocity();
    2235         rho_water=matpar->GetRhoWater();
    2236         rho_ice=matpar->GetRhoIce();
    2237         heatcapacity=matpar->GetHeatCapacity();
    2238         GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
    2239         for(i=0;i<NUMVERTICES2D;i++) for(j=0;j<3;j++) xyz_list_tria[i][j]=xyz_list[i][j];
    2240 
    2241         /* Start looping on the number of gauss (nodes on the bedrock) */
    2242         gauss=new GaussPenta(0,1,2,2);
    2243         for (ig=gauss->begin();ig<gauss->end();ig++){
    2244 
    2245                 gauss->GaussPoint(ig);
    2246                
    2247                 GetTriaJacobianDeterminant(&Jdet2d, &xyz_list_tria[0][0], gauss);
    2248                 GetNodalFunctionsP1(&basis[0], gauss);
    2249                                
    2250                 D_scalar=gauss->weight*Jdet2d*rho_water*mixed_layer_capacity*thermal_exchange_velocity/(heatcapacity*rho_ice);
    2251                 if(dt) D_scalar=dt*D_scalar;
    2252 
    2253                 TripleMultiply(&basis[0],numdof,1,0,
    2254                                         &D_scalar,1,1,0,
    2255                                         &basis[0],1,numdof,0,
    2256                                         &Ke->values[0],1);
    2257         }
    2258        
    2259         /*Clean up and return*/
    2260         delete gauss;
    2261         return Ke;
    2262 }
    2263 /*}}}*/
    2264 /*FUNCTION Penta::CreatePVectorEnthalpy {{{1*/
    2265 ElementVector* Penta::CreatePVectorEnthalpy(void){
    2266 
    2267         /*compute all load vectors for this element*/
    2268         ElementVector* pe1=CreatePVectorEnthalpyVolume();
    2269         ElementVector* pe2=CreatePVectorEnthalpySheet();
    2270         ElementVector* pe3=CreatePVectorEnthalpyShelf();
    2271         ElementVector* pe =new ElementVector(pe1,pe2,pe3);
    2272 
    2273         /*clean-up and return*/
    2274         delete pe1;
    2275         delete pe2;
    2276         delete pe3;
    2277         return pe;
    2278 }
    2279 /*}}}*/
    2280 /*FUNCTION Penta::CreatePVectorEnthalpyVolume {{{1*/
    2281 ElementVector* Penta::CreatePVectorEnthalpyVolume(void){
    2282 
    2283         /*Constants*/
    2284         const int  numdof=NUMVERTICES*NDOF1;
    2285 
    2286         /*Intermediaries*/
    2287         int    i,j,ig,found=0;
    2288         int    friction_type,stabilization;
    2289         double Jdet,phi,dt;
    2290         double rho_ice,heatcapacity;
    2291         double thermalconductivity;
    2292         double viscosity,temperature;
    2293         double tau_parameter,diameter;
    2294         double u,v,w;
    2295         double scalar_def,scalar_transient;
    2296         double temperature_list[NUMVERTICES];
    2297         double xyz_list[NUMVERTICES][3];
    2298         double L[numdof];
    2299         double dbasis[3][6];
    2300         double epsilon[6];
    2301         GaussPenta *gauss=NULL;
    2302 
    2303         /*Initialize Element vector*/
    2304         ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters);
    2305 
    2306         /*Retrieve all inputs and parameters*/
    2307         GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
    2308         rho_ice=matpar->GetRhoIce();
    2309         heatcapacity=matpar->GetHeatCapacity();
    2310         thermalconductivity=matpar->GetThermalConductivity();
    2311         this->parameters->FindParam(&dt,TimesteppingTimeStepEnum);
    2312         this->parameters->FindParam(&stabilization,ThermalStabilizationEnum);
    2313         Input* vx_input=inputs->GetInput(VxEnum); _assert_(vx_input);
    2314         Input* vy_input=inputs->GetInput(VyEnum); _assert_(vy_input);
    2315         Input* vz_input=inputs->GetInput(VzEnum); _assert_(vz_input);
    2316         Input* temperature_input=NULL;
    2317         if (dt) temperature_input=inputs->GetInput(TemperatureEnum); _assert_(inputs);
    2318         if (stabilization==2) diameter=MinEdgeLength(xyz_list);
    2319 
    2320         /* Start  looping on the number of gaussian points: */
    2321         gauss=new GaussPenta(2,3);
    2322         for (ig=gauss->begin();ig<gauss->end();ig++){
    2323 
    2324                 gauss->GaussPoint(ig);
    2325 
    2326                 GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss);
    2327                 GetNodalFunctionsP1(&L[0], gauss);
    2328 
    2329                 this->GetStrainRate3d(&epsilon[0],&xyz_list[0][0],gauss,vx_input,vy_input,vz_input);
    2330                 matice->GetViscosity3dStokes(&viscosity,&epsilon[0]);
    2331                 GetPhi(&phi, &epsilon[0], viscosity);
    2332 
    2333                 scalar_def=phi/(rho_ice)*Jdet*gauss->weight;
    2334                 if(dt) scalar_def=scalar_def*dt;
    2335 
    2336                 for(i=0;i<NUMVERTICES;i++)  pe->values[i]+=scalar_def*L[i];
    2337 
    2338                 /* Build transient now */
    2339                 if(dt){
    2340                         temperature_input->GetParameterValue(&temperature, gauss);
    2341                         scalar_transient=temperature*Jdet*gauss->weight;
    2342                         for(i=0;i<NUMVERTICES;i++)  pe->values[i]+=scalar_transient*L[i];
    2343                 }
    2344 
    2345                 if(stabilization==2){
    2346                         GetNodalFunctionsP1Derivatives(&dbasis[0][0],&xyz_list[0][0], gauss);
    2347 
    2348                         vx_input->GetParameterValue(&u, gauss);
    2349                         vy_input->GetParameterValue(&v, gauss);
    2350                         vz_input->GetParameterValue(&w, gauss);
    2351 
    2352                         tau_parameter=GetStabilizationParameter(u,v,w,diameter,rho_ice,heatcapacity,thermalconductivity);
    2353 
    2354                         for(i=0;i<NUMVERTICES;i++)  pe->values[i]+=tau_parameter*scalar_def*(u*dbasis[0][i]+v*dbasis[1][i]+w*dbasis[2][i]);
    2355                         if(dt){
    2356                                 for(i=0;i<NUMVERTICES;i++)  pe->values[i]+=tau_parameter*scalar_transient*(u*dbasis[0][i]+v*dbasis[1][i]+w*dbasis[2][i]);
    2357                         }
    2358                 }
    2359         }
    2360 
    2361         /*Clean up and return*/
    2362         delete gauss;
    2363         return pe;
    2364 }
    2365 /*}}}*/
    2366 /*FUNCTION Penta::CreatePVectorEnthalpyShelf {{{1*/
    2367 ElementVector* Penta::CreatePVectorEnthalpyShelf(void){
    2368 
    2369         /*Constants*/
    2370         const int  numdof=NUMVERTICES*NDOF1;
    2371 
    2372         /*Intermediaries */
    2373         int        i,j,ig;
    2374         double     Jdet2d;
    2375         double     heatcapacity,h_pmp;
    2376         double     mixed_layer_capacity,thermal_exchange_velocity;
    2377         double     rho_ice,rho_water,pressure,dt,scalar_ocean;
    2378         double     xyz_list[NUMVERTICES][3];
    2379         double     xyz_list_tria[NUMVERTICES2D][3];
    2380         double     basis[NUMVERTICES];
    2381         GaussPenta* gauss=NULL;
    2382 
    2383         /*Initialize Element vector*/
    2384         ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters);
    2385 
    2386         /* Ice/ocean heat exchange flux on ice shelf base */
    2387         if (!IsOnBed() || !IsOnShelf()) return NULL;
    2388 
    2389         /*Retrieve all inputs and parameters*/
    2390         GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
    2391         for(i=0;i<NUMVERTICES2D;i++) for(j=0;j<3;j++) xyz_list_tria[i][j]=xyz_list[i][j];
    2392         mixed_layer_capacity=matpar->GetMixedLayerCapacity();
    2393         thermal_exchange_velocity=matpar->GetThermalExchangeVelocity();
    2394         rho_water=matpar->GetRhoWater();
    2395         rho_ice=matpar->GetRhoIce();
    2396         heatcapacity=matpar->GetHeatCapacity();
    2397         this->parameters->FindParam(&dt,TimesteppingTimeStepEnum);
    2398         Input* pressure_input=inputs->GetInput(PressureEnum); _assert_(pressure_input);
    2399 
    2400         /* Start looping on the number of gauss 2d (nodes on the bedrock) */
    2401         gauss=new GaussPenta(0,1,2,2);
    2402         for(ig=gauss->begin();ig<gauss->end();ig++){
    2403 
    2404                 gauss->GaussPoint(ig);
    2405 
    2406                 GetTriaJacobianDeterminant(&Jdet2d, &xyz_list_tria[0][0], gauss);
    2407                 GetNodalFunctionsP1(&basis[0], gauss);
    2408 
    2409                 pressure_input->GetParameterValue(&pressure,gauss);
    2410                 h_pmp=matpar->PureIceEnthalpy(pressure);
    2411 
    2412                 scalar_ocean=gauss->weight*Jdet2d*rho_water*mixed_layer_capacity*thermal_exchange_velocity*(h_pmp)/(rho_ice*heatcapacity);
    2413                 if(dt) scalar_ocean=dt*scalar_ocean;
    2414 
    2415                 for(i=0;i<numdof;i++) pe->values[i]+=scalar_ocean*basis[i];
    2416         }
    2417 
    2418         /*Clean up and return*/
    2419         delete gauss;
    2420         return pe;
    2421 }
    2422 /*}}}*/
    2423 /*FUNCTION Penta::CreatePVectorEnthalpySheet {{{1*/
    2424 ElementVector* Penta::CreatePVectorEnthalpySheet(void){
    2425 
    2426         /*Constants*/
    2427         const int  numdof=NUMVERTICES*NDOF1;
    2428 
    2429         /*Intermediaries */
    2430         int        i,j,ig;
    2431         int        analysis_type;
    2432         double     xyz_list[NUMVERTICES][3];
    2433         double     xyz_list_tria[NUMVERTICES2D][3]={0.0};
    2434         double     Jdet2d,dt;
    2435         double     rho_ice,heatcapacity,geothermalflux_value;
    2436         double     basalfriction,alpha2,vx,vy;
    2437         double     scalar;
    2438         double     basis[NUMVERTICES];
    2439         Friction*  friction=NULL;
    2440         GaussPenta* gauss=NULL;
    2441 
    2442         /* Geothermal flux on ice sheet base and basal friction */
    2443         if (!IsOnBed() || IsOnShelf()) return NULL;
    2444 
    2445         /*Initialize Element vector*/
    2446         ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters);
    2447 
    2448         /*Retrieve all inputs and parameters*/
    2449         GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
    2450         for(i=0;i<NUMVERTICES2D;i++) for(j=0;j<2;j++) xyz_list_tria[i][j]=xyz_list[i][j];
    2451         parameters->FindParam(&analysis_type,AnalysisTypeEnum);
    2452         rho_ice=matpar->GetRhoIce();
    2453         heatcapacity=matpar->GetHeatCapacity();
    2454         this->parameters->FindParam(&dt,TimesteppingTimeStepEnum);
    2455         Input* vx_input=inputs->GetInput(VxEnum);                         _assert_(vx_input);
    2456         Input* vy_input=inputs->GetInput(VyEnum);                         _assert_(vy_input);
    2457         Input* vz_input=inputs->GetInput(VzEnum);                         _assert_(vz_input);
    2458         Input* geothermalflux_input=inputs->GetInput(BasalforcingsGeothermalfluxEnum); _assert_(geothermalflux_input);
    2459 
    2460         /*Build frictoin element, needed later: */
    2461         friction=new Friction("3d",inputs,matpar,analysis_type);
    2462 
    2463         /* Start looping on the number of gauss 2d (nodes on the bedrock) */
    2464         gauss=new GaussPenta(0,1,2,2);
    2465         for(ig=gauss->begin();ig<gauss->end();ig++){
    2466 
    2467                 gauss->GaussPoint(ig);
    2468 
    2469                 GetTriaJacobianDeterminant(&Jdet2d, &xyz_list_tria[0][0], gauss);
    2470                 GetNodalFunctionsP1(&basis[0], gauss);
    2471 
    2472                 geothermalflux_input->GetParameterValue(&geothermalflux_value,gauss);
    2473                 friction->GetAlpha2(&alpha2,gauss,VxEnum,VyEnum,VzEnum);
    2474                 vx_input->GetParameterValue(&vx,gauss);
    2475                 vy_input->GetParameterValue(&vy,gauss);
    2476                 basalfriction=alpha2*(pow(vx,2.0)+pow(vy,2.0));
    2477                
    2478                 scalar=gauss->weight*Jdet2d*(basalfriction+geothermalflux_value)/(rho_ice);
    2479                 if(dt) scalar=dt*scalar;
    2480 
    2481                 for(i=0;i<numdof;i++) pe->values[i]+=scalar*basis[i];
    2482         }
    2483 
    2484         /*Clean up and return*/
    2485         delete gauss;
    2486         delete friction;
    2487         return pe;
    2488 }
    2489 /*}}}*/
    2490 /*FUNCTION Penta::CreatePVectorMelting {{{1*/
    2491 ElementVector* Penta::CreatePVectorMelting(void){
    2492         return NULL;
    2493 }
    2494 /*}}}*/
    2495 /*FUNCTION Penta::CreatePVectorThermal {{{1*/
    2496 ElementVector* Penta::CreatePVectorThermal(void){
    2497 
    2498         /*compute all load vectors for this element*/
    2499         ElementVector* pe1=CreatePVectorThermalVolume();
    2500         ElementVector* pe2=CreatePVectorThermalSheet();
    2501         ElementVector* pe3=CreatePVectorThermalShelf();
    2502         ElementVector* pe =new ElementVector(pe1,pe2,pe3);
    2503 
    2504         /*clean-up and return*/
    2505         delete pe1;
    2506         delete pe2;
    2507         delete pe3;
    2508         return pe;
    2509 }
    2510 /*}}}*/
    2511 /*FUNCTION Penta::CreatePVectorThermalVolume {{{1*/
    2512 ElementVector* Penta::CreatePVectorThermalVolume(void){
    2513 
    2514         /*Constants*/
    2515         const int  numdof=NUMVERTICES*NDOF1;
    2516 
    2517         /*Intermediaries*/
    2518         int    i,j,ig,found=0;
    2519         int    friction_type,stabilization;
    2520         double Jdet,phi,dt;
    2521         double rho_ice,heatcapacity;
    2522         double thermalconductivity;
    2523         double viscosity,temperature;
    2524         double tau_parameter,diameter;
    2525         double u,v,w;
    2526         double scalar_def,scalar_transient;
    2527         double temperature_list[NUMVERTICES];
    2528         double xyz_list[NUMVERTICES][3];
    2529         double L[numdof];
    2530         double dbasis[3][6];
    2531         double epsilon[6];
    2532         GaussPenta *gauss=NULL;
    2533 
    2534         /*Initialize Element vector*/
    2535         ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters);
    2536 
    2537         /*Retrieve all inputs and parameters*/
    2538         GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
    2539         rho_ice=matpar->GetRhoIce();
    2540         heatcapacity=matpar->GetHeatCapacity();
    2541         thermalconductivity=matpar->GetThermalConductivity();
    2542         this->parameters->FindParam(&dt,TimesteppingTimeStepEnum);
    2543         this->parameters->FindParam(&stabilization,ThermalStabilizationEnum);
    2544         Input* vx_input=inputs->GetInput(VxEnum); _assert_(vx_input);
    2545         Input* vy_input=inputs->GetInput(VyEnum); _assert_(vy_input);
    2546         Input* vz_input=inputs->GetInput(VzEnum); _assert_(vz_input);
    2547         Input* temperature_input=NULL;
    2548         if (dt) temperature_input=inputs->GetInput(TemperatureEnum); _assert_(inputs);
    2549         if (stabilization==2) diameter=MinEdgeLength(xyz_list);
    2550 
    2551         /* Start  looping on the number of gaussian points: */
    2552         gauss=new GaussPenta(2,3);
    2553         for (ig=gauss->begin();ig<gauss->end();ig++){
    2554 
    2555                 gauss->GaussPoint(ig);
    2556 
    2557                 GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss);
    2558                 GetNodalFunctionsP1(&L[0], gauss);
    2559 
    2560                 this->GetStrainRate3d(&epsilon[0],&xyz_list[0][0],gauss,vx_input,vy_input,vz_input);
    2561                 matice->GetViscosity3dStokes(&viscosity,&epsilon[0]);
    2562                 GetPhi(&phi, &epsilon[0], viscosity);
    2563 
    2564                 scalar_def=phi/(rho_ice*heatcapacity)*Jdet*gauss->weight;
    2565                 if(dt) scalar_def=scalar_def*dt;
    2566 
    2567                 for(i=0;i<NUMVERTICES;i++)  pe->values[i]+=scalar_def*L[i];
    2568 
    2569                 /* Build transient now */
    2570                 if(dt){
    2571                         temperature_input->GetParameterValue(&temperature, gauss);
    2572                         scalar_transient=temperature*Jdet*gauss->weight;
    2573                         for(i=0;i<NUMVERTICES;i++)  pe->values[i]+=scalar_transient*L[i];
    2574                 }
    2575 
    2576                 if(stabilization==2){
    2577                         GetNodalFunctionsP1Derivatives(&dbasis[0][0],&xyz_list[0][0], gauss);
    2578 
    2579                         vx_input->GetParameterValue(&u, gauss);
    2580                         vy_input->GetParameterValue(&v, gauss);
    2581                         vz_input->GetParameterValue(&w, gauss);
    2582 
    2583                         tau_parameter=GetStabilizationParameter(u,v,w,diameter,rho_ice,heatcapacity,thermalconductivity);
    2584 
    2585                         for(i=0;i<NUMVERTICES;i++)  pe->values[i]+=tau_parameter*scalar_def*(u*dbasis[0][i]+v*dbasis[1][i]+w*dbasis[2][i]);
    2586                         if(dt){
    2587                                 for(i=0;i<NUMVERTICES;i++)  pe->values[i]+=tau_parameter*scalar_transient*(u*dbasis[0][i]+v*dbasis[1][i]+w*dbasis[2][i]);
    2588                         }
    2589                 }
    2590         }
    2591 
    2592         /*Clean up and return*/
    2593         delete gauss;
    2594         return pe;
    2595 }
    2596 /*}}}*/
    2597 /*FUNCTION Penta::CreatePVectorThermalShelf {{{1*/
    2598 ElementVector* Penta::CreatePVectorThermalShelf(void){
    2599 
    2600         /*Constants*/
    2601         const int  numdof=NUMVERTICES*NDOF1;
    2602 
    2603         /*Intermediaries */
    2604         int        i,j,ig;
    2605         double     Jdet2d;
    2606         double     mixed_layer_capacity,thermal_exchange_velocity;
    2607         double     rho_ice,rho_water,pressure,dt,scalar_ocean;
    2608         double     heatcapacity,t_pmp;
    2609         double     xyz_list[NUMVERTICES][3];
    2610         double     xyz_list_tria[NUMVERTICES2D][3];
    2611         double     basis[NUMVERTICES];
    2612         GaussPenta* gauss=NULL;
    2613 
    2614         /* Ice/ocean heat exchange flux on ice shelf base */
    2615         if (!IsOnBed() || !IsOnShelf()) return NULL;
    2616 
    2617         /*Initialize Element vector*/
    2618         ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters);
    2619 
    2620         /*Retrieve all inputs and parameters*/
    2621         GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
    2622         for(i=0;i<NUMVERTICES2D;i++) for(j=0;j<3;j++) xyz_list_tria[i][j]=xyz_list[i][j];
    2623         mixed_layer_capacity=matpar->GetMixedLayerCapacity();
    2624         thermal_exchange_velocity=matpar->GetThermalExchangeVelocity();
    2625         rho_water=matpar->GetRhoWater();
    2626         rho_ice=matpar->GetRhoIce();
    2627         heatcapacity=matpar->GetHeatCapacity();
    2628         this->parameters->FindParam(&dt,TimesteppingTimeStepEnum);
    2629         Input* pressure_input=inputs->GetInput(PressureEnum); _assert_(pressure_input);
    2630 
    2631         /* Start looping on the number of gauss 2d (nodes on the bedrock) */
    2632         gauss=new GaussPenta(0,1,2,2);
    2633         for(ig=gauss->begin();ig<gauss->end();ig++){
    2634 
    2635                 gauss->GaussPoint(ig);
    2636 
    2637                 GetTriaJacobianDeterminant(&Jdet2d, &xyz_list_tria[0][0], gauss);
    2638                 GetNodalFunctionsP1(&basis[0], gauss);
    2639 
    2640                 pressure_input->GetParameterValue(&pressure,gauss);
    2641                 t_pmp=matpar->TMeltingPoint(pressure);
    2642 
    2643                 scalar_ocean=gauss->weight*Jdet2d*rho_water*mixed_layer_capacity*thermal_exchange_velocity*(t_pmp)/(heatcapacity*rho_ice);
    2644                 if(dt) scalar_ocean=dt*scalar_ocean;
    2645 
    2646                 for(i=0;i<numdof;i++) pe->values[i]+=scalar_ocean*basis[i];
    2647         }
    2648 
    2649         /*Clean up and return*/
    2650         delete gauss;
    2651         return pe;
    2652 }
    2653 /*}}}*/
    2654 /*FUNCTION Penta::CreatePVectorThermalSheet {{{1*/
    2655 ElementVector* Penta::CreatePVectorThermalSheet(void){
    2656 
    2657         /*Constants*/
    2658         const int  numdof=NUMVERTICES*NDOF1;
    2659 
    2660         /*Intermediaries */
    2661         int        i,j,ig;
    2662         int        analysis_type;
    2663         double     xyz_list[NUMVERTICES][3];
    2664         double     xyz_list_tria[NUMVERTICES2D][3]={0.0};
    2665         double     Jdet2d,dt;
    2666         double     rho_ice,heatcapacity,geothermalflux_value;
    2667         double     basalfriction,alpha2,vx,vy;
    2668         double     scalar;
    2669         double     basis[NUMVERTICES];
    2670         Friction*  friction=NULL;
    2671         GaussPenta* gauss=NULL;
    2672 
    2673         /* Geothermal flux on ice sheet base and basal friction */
    2674         if (!IsOnBed() || IsOnShelf()) return NULL;
    2675 
    2676         /*Initialize Element vector*/
    2677         ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters);
    2678 
    2679         /*Retrieve all inputs and parameters*/
    2680         GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
    2681         for(i=0;i<NUMVERTICES2D;i++) for(j=0;j<2;j++) xyz_list_tria[i][j]=xyz_list[i][j];
    2682         parameters->FindParam(&analysis_type,AnalysisTypeEnum);
    2683         rho_ice=matpar->GetRhoIce();
    2684         heatcapacity=matpar->GetHeatCapacity();
    2685         this->parameters->FindParam(&dt,TimesteppingTimeStepEnum);
    2686         Input* vx_input=inputs->GetInput(VxEnum);                         _assert_(vx_input);
    2687         Input* vy_input=inputs->GetInput(VyEnum);                         _assert_(vy_input);
    2688         Input* vz_input=inputs->GetInput(VzEnum);                         _assert_(vz_input);
    2689         Input* geothermalflux_input=inputs->GetInput(BasalforcingsGeothermalfluxEnum); _assert_(geothermalflux_input);
    2690 
    2691         /*Build frictoin element, needed later: */
    2692         friction=new Friction("3d",inputs,matpar,analysis_type);
    2693 
    2694         /* Start looping on the number of gauss 2d (nodes on the bedrock) */
    2695         gauss=new GaussPenta(0,1,2,2);
    2696         for(ig=gauss->begin();ig<gauss->end();ig++){
    2697 
    2698                 gauss->GaussPoint(ig);
    2699 
    2700                 GetTriaJacobianDeterminant(&Jdet2d, &xyz_list_tria[0][0], gauss);
    2701                 GetNodalFunctionsP1(&basis[0], gauss);
    2702 
    2703                 geothermalflux_input->GetParameterValue(&geothermalflux_value,gauss);
    2704                 friction->GetAlpha2(&alpha2,gauss,VxEnum,VyEnum,VzEnum);
    2705                 vx_input->GetParameterValue(&vx,gauss);
    2706                 vy_input->GetParameterValue(&vy,gauss);
    2707                 basalfriction=alpha2*(pow(vx,2.0)+pow(vy,2.0));
    2708                
    2709                 scalar=gauss->weight*Jdet2d*(basalfriction+geothermalflux_value)/(heatcapacity*rho_ice);
    2710                 if(dt) scalar=dt*scalar;
    2711 
    2712                 for(i=0;i<numdof;i++) pe->values[i]+=scalar*basis[i];
    2713         }
    2714 
    2715         /*Clean up and return*/
    2716         delete gauss;
    2717         delete friction;
    2718         return pe;
    2719 }
    2720 /*}}}*/
    2721 /*FUNCTION Penta::GetSolutionFromInputsThermal{{{1*/
    2722 void  Penta::GetSolutionFromInputsThermal(Vec solution){
    2723 
    2724         const int    numdof=NDOF1*NUMVERTICES;
    2725 
    2726         int          i;
    2727         int*         doflist=NULL;
    2728         double       values[numdof];
    2729         double       temp;
    2730         GaussPenta   *gauss=NULL;
    2731 
    2732         /*Get dof list: */
    2733         GetDofList(&doflist,NoneApproximationEnum,GsetEnum);
    2734         Input* t_input=inputs->GetInput(TemperatureEnum); _assert_(t_input);
    2735 
    2736         gauss=new GaussPenta();
    2737         for(i=0;i<NUMVERTICES;i++){
    2738                 /*Recover temperature*/
    2739                 gauss->GaussVertex(i);
    2740                 t_input->GetParameterValue(&temp,gauss);
    2741                 values[i]=temp;
    2742         }
    2743 
    2744         /*Add value to global vector*/
    2745         VecSetValues(solution,numdof,doflist,(const double*)values,INSERT_VALUES);
    2746 
    2747         /*Free ressources:*/
    2748         delete gauss;
    2749         xfree((void**)&doflist);
    2750 }
    2751 /*}}}*/
    2752 /*FUNCTION Penta::GetSolutionFromInputsEnthalpy{{{1*/
    2753 void  Penta::GetSolutionFromInputsEnthalpy(Vec solution){
    2754 
    2755         const int    numdof=NDOF1*NUMVERTICES;
    2756 
    2757         int          i;
    2758         int*         doflist=NULL;
    2759         double       values[numdof];
    2760         double       enthalpy;
    2761         GaussPenta   *gauss=NULL;
    2762 
    2763         /*Get dof list: */
    2764         GetDofList(&doflist,NoneApproximationEnum,GsetEnum);
    2765         Input* h_input=inputs->GetInput(EnthalpyEnum); _assert_(h_input);
    2766 
    2767         gauss=new GaussPenta();
    2768         for(i=0;i<NUMVERTICES;i++){
    2769                 /*Recover temperature*/
    2770                 gauss->GaussVertex(i);
    2771                 h_input->GetParameterValue(&enthalpy,gauss);
    2772                 values[i]=enthalpy;
    2773         }
    2774 
    2775         /*Add value to global vector*/
    2776         VecSetValues(solution,numdof,doflist,(const double*)values,INSERT_VALUES);
    2777 
    2778         /*Free ressources:*/
    2779         delete gauss;
    2780         xfree((void**)&doflist);
    2781 }
    2782 /*}}}*/
    2783 /*FUNCTION Penta::InputUpdateFromSolutionThermal {{{1*/
    2784 void  Penta::InputUpdateFromSolutionThermal(double* solution){
    2785 
    2786         const int    numdof=NDOF1*NUMVERTICES;
    2787 
    2788         bool   converged;
    2789         int    i,rheology_law;
    2790         double xyz_list[NUMVERTICES][3];
    2791         double values[numdof];
    2792         double B[numdof];
    2793         double B_average,s_average;
    2794         int*   doflist=NULL;
    2795 
    2796         /*Get dof list: */
    2797         GetDofList(&doflist,NoneApproximationEnum,GsetEnum);
    2798 
    2799         /*Use the dof list to index into the solution vector: */
    2800         for(i=0;i<numdof;i++){
    2801                 values[i]=solution[doflist[i]];
    2802 
    2803                 /*Check solution*/
    2804                 if(isnan(values[i])) _error_("NaN found in solution vector");
    2805                 //if(values[i]<0)      printf("temperature < 0°K found in solution vector\n");
    2806                 //if(values[i]>275)    printf("temperature > 275°K found in solution vector (Paterson's rheology associated is negative)\n");
    2807         }
    2808 
    2809         /*Get all inputs and parameters*/
    2810         GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
    2811         Input* surface_input=inputs->GetInput(SurfaceEnum); _assert_(surface_input);
    2812 
    2813         this->inputs->GetParameterValue(&converged,ConvergedEnum);
    2814         if(converged){
    2815                 this->inputs->AddInput(new PentaVertexInput(TemperatureEnum,values));
    2816 
    2817                 /*Update Rheology only if converged (we must make sure that the temperature is below melting point
    2818                  * otherwise the rheology could be negative*/
    2819                 this->parameters->FindParam(&rheology_law,MaterialsRheologyLawEnum);
    2820                 switch(rheology_law){
    2821                         case NoneEnum:
    2822                                 /*Do nothing: B is not temperature dependent*/
    2823                                 break;
    2824                         case PatersonEnum:
    2825                                 B_average=Paterson((values[0]+values[1]+values[2]+values[3]+values[4]+values[5])/6.0);
    2826                                 for(i=0;i<numdof;i++) B[i]=B_average;
    2827                                 this->matice->inputs->AddInput(new PentaVertexInput(MaterialsRheologyBEnum,B));
    2828                                 break;
    2829                         case ArrheniusEnum:
    2830                                 surface_input->GetParameterAverage(&s_average);
    2831                                 B_average=Arrhenius((values[0]+values[1]+values[2]+values[3]+values[4]+values[5])/6.0,
    2832                                                         s_average-((xyz_list[0][2]+xyz_list[1][2]+xyz_list[2][2]+xyz_list[3][2]+xyz_list[4][2]+xyz_list[5][2])/6.0),
    2833                                                         matice->GetN());
    2834                                 for(i=0;i<numdof;i++) B[i]=B_average;
    2835                                 this->matice->inputs->AddInput(new PentaVertexInput(MaterialsRheologyBEnum,B));
    2836                                 break;
    2837                         default:
    2838                                 _error_("Rheology law %s not supported yet",EnumToStringx(rheology_law));
    2839 
    2840                 }
    2841         }
    2842         else{
    2843                 this->inputs->AddInput(new PentaVertexInput(TemperaturePicardEnum,values));
    2844         }
    2845 
    2846         /*Free ressources:*/
    2847         xfree((void**)&doflist);
    2848 }
    2849 /*}}}*/
    2850 /*FUNCTION Penta::InputUpdateFromSolutionEnthalpy {{{1*/
    2851 void  Penta::InputUpdateFromSolutionEnthalpy(double* solution){
    2852 
    2853         const int    numdof=NDOF1*NUMVERTICES;
    2854 
    2855         bool   converged;
    2856         int    i,rheology_law;
    2857         double xyz_list[NUMVERTICES][3];
    2858         double values[numdof];
    2859         double pressure[NUMVERTICES];
    2860         double temperatures[numdof];
    2861         double waterfraction[numdof];
    2862         double B[numdof];
    2863         double B_average,s_average;
    2864         int*   doflist=NULL;
    2865 
    2866         /*Get dof list: */
    2867         GetDofList(&doflist,NoneApproximationEnum,GsetEnum);
    2868 
    2869         /*Use the dof list to index into the solution vector: */
    2870         for(i=0;i<numdof;i++){
    2871                 values[i]=solution[doflist[i]];
    2872 
    2873                 /*Check solution*/
    2874                 if(isnan(values[i])) _error_("NaN found in solution vector");
    2875         }
    2876 
    2877         /*Get all inputs and parameters*/
    2878         GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
    2879         GetParameterListOnVertices(&pressure[0],PressureEnum);
    2880         Input* surface_input=inputs->GetInput(SurfaceEnum); _assert_(surface_input);
    2881        
    2882 
    2883 //      this->inputs->GetParameterValue(&converged,ConvergedEnum);
    2884 //      if(converged){
    2885                 /*Convert enthalpy into temperature and water fraction*/
    2886                 for(i=0;i<numdof;i++) matpar->EnthalpyToThermal(&temperatures[i],&waterfraction[i],values[i],pressure[i]);
    2887                        
    2888                 this->inputs->AddInput(new PentaVertexInput(EnthalpyEnum,values));
    2889                 this->inputs->AddInput(new PentaVertexInput(WaterfractionEnum,waterfraction));
    2890                 this->inputs->AddInput(new PentaVertexInput(TemperatureEnum,temperatures));
    2891 
    2892                 /*Update Rheology only if converged (we must make sure that the temperature is below melting point
    2893                  * otherwise the rheology could be negative*/
    2894                 this->parameters->FindParam(&rheology_law,MaterialsRheologyLawEnum);
    2895                 switch(rheology_law){
    2896                         case NoneEnum:
    2897                                 /*Do nothing: B is not temperature dependent*/
    2898                                 break;
    2899                         case PatersonEnum:
    2900                                 B_average=Paterson((temperatures[0]+temperatures[1]+temperatures[2]+temperatures[3]+temperatures[4]+temperatures[5])/6.0);
    2901                                 for(i=0;i<numdof;i++) B[i]=B_average;
    2902                                 this->matice->inputs->AddInput(new PentaVertexInput(MaterialsRheologyBEnum,B));
    2903                                 break;
    2904                         case ArrheniusEnum:
    2905                                 surface_input->GetParameterAverage(&s_average);
    2906                                 B_average=Arrhenius((temperatures[0]+temperatures[1]+temperatures[2]+temperatures[3]+temperatures[4]+temperatures[5])/6.0,
    2907                                                         s_average-((xyz_list[0][2]+xyz_list[1][2]+xyz_list[2][2]+xyz_list[3][2]+xyz_list[4][2]+xyz_list[5][2])/6.0),
    2908                                                         matice->GetN());
    2909                                 for(i=0;i<numdof;i++) B[i]=B_average;
    2910                                 this->matice->inputs->AddInput(new PentaVertexInput(MaterialsRheologyBEnum,B));
    2911                                 break;
    2912                         default:
    2913                                 _error_("Rheology law %s not supported yet",EnumToStringx(rheology_law));
    2914 
    2915                 }
    2916 //      }
    2917 //      else{
    2918 //              this->inputs->AddInput(new PentaVertexInput(EnthalpyPicardEnum,values));
    2919 //      }
    2920 
    2921         /*Free ressources:*/
    2922         xfree((void**)&doflist);
    2923 }
    2924 /*}}}*/
    2925 #endif
    2926 
    2927 #ifdef _HAVE_CONTROL_
    2928 /*FUNCTION Penta::ControlInputGetGradient{{{1*/
    2929 void Penta::ControlInputGetGradient(Vec gradient,int enum_type){
    2930 
    2931         int doflist1[NUMVERTICES];
    2932         Input* input=NULL;
    2933 
    2934         if(enum_type==MaterialsRheologyBbarEnum){
    2935                 if(!IsOnBed()) return;
    2936                 input=(Input*)matice->inputs->GetInput(MaterialsRheologyBEnum);
    2937         }
    2938         else{
    2939                 input=inputs->GetInput(enum_type);
    2940         }
    2941         if (!input) _error_("Input %s not found",EnumToStringx(enum_type));
    2942         if (input->Enum()!=ControlInputEnum) _error_("Input %s is not a ControlInput",EnumToStringx(enum_type));
    2943 
    2944         this->GetDofList1(&doflist1[0]);
    2945         ((ControlInput*)input)->GetGradient(gradient,&doflist1[0]);
    2946 
    2947 }/*}}}*/
    2948 /*FUNCTION Penta::ControlInputScaleGradient{{{1*/
    2949 void Penta::ControlInputScaleGradient(int enum_type,double scale){
    2950 
    2951         Input* input=NULL;
    2952 
    2953         if(enum_type==MaterialsRheologyBbarEnum){
    2954                 input=(Input*)matice->inputs->GetInput(MaterialsRheologyBEnum);
    2955         }
    2956         else{
    2957                 input=inputs->GetInput(enum_type);
    2958         }
    2959         if (!input) _error_("Input %s not found",EnumToStringx(enum_type));
    2960         if (input->Enum()!=ControlInputEnum) _error_("Input %s is not a ControlInput",EnumToStringx(enum_type));
    2961 
    2962         ((ControlInput*)input)->ScaleGradient(scale);
    2963 }/*}}}*/
    2964 /*FUNCTION Penta::ControlInputSetGradient{{{1*/
    2965 void Penta::ControlInputSetGradient(double* gradient,int enum_type){
    2966 
    2967         int    doflist1[NUMVERTICES];
    2968         double grad_list[NUMVERTICES];
    2969         Input* grad_input=NULL;
    2970         Input* input=NULL;
    2971 
    2972         if(enum_type==MaterialsRheologyBbarEnum){
    2973                 input=(Input*)matice->inputs->GetInput(MaterialsRheologyBEnum);
    2974         }
    2975         else{
    2976                 input=inputs->GetInput(enum_type);
    2977         }
    2978         if (!input) _error_("Input %s not found",EnumToStringx(enum_type));
    2979         if (input->Enum()!=ControlInputEnum) _error_("Input %s is not a ControlInput",EnumToStringx(enum_type));
    2980 
    2981         this->GetDofList1(&doflist1[0]);
    2982         for(int i=0;i<NUMVERTICES;i++) grad_list[i]=gradient[doflist1[i]];
    2983         grad_input=new PentaVertexInput(GradientEnum,grad_list);
    2984         ((ControlInput*)input)->SetGradient(grad_input);
    2985 
    2986 }/*}}}*/
    2987 /*FUNCTION Penta::CreatePVectorAdjointHoriz{{{1*/
    2988 ElementVector* Penta::CreatePVectorAdjointHoriz(void){
    2989 
    2990         int approximation;
    2991         inputs->GetParameterValue(&approximation,ApproximationEnum);
    2992 
    2993         switch(approximation){
    2994                 case MacAyealApproximationEnum:
    2995                         return CreatePVectorAdjointMacAyeal();
    2996                 case PattynApproximationEnum:
    2997                         return CreatePVectorAdjointPattyn();
    2998                 case NoneApproximationEnum:
    2999                         return NULL;
    3000                 case StokesApproximationEnum:
    3001                         return CreatePVectorAdjointStokes();
    3002                 default:
    3003                         _error_("Approximation %s not supported yet",EnumToStringx(approximation));
    3004         }
    3005 }
    3006 /*}}}*/
    3007 /*FUNCTION Penta::CreatePVectorAdjointMacAyeal{{{1*/
    3008 ElementVector* Penta::CreatePVectorAdjointMacAyeal(){
    3009 
    3010         if (!IsOnBed()) return NULL;
    3011 
    3012         /*Call Tria function*/
    3013         Tria* tria=(Tria*)SpawnTria(0,1,2); //nodes 0, 1 and 2 make the new tria.
    3014         ElementVector* pe=tria->CreatePVectorAdjointHoriz();
    3015         delete tria->matice; delete tria;
    3016 
    3017         /*clean up and return*/
    3018         return pe;
    3019 }
    3020 /*}}}*/
    3021 /*FUNCTION Penta::CreatePVectorAdjointPattyn{{{1*/
    3022 ElementVector* Penta::CreatePVectorAdjointPattyn(void){
    3023 
    3024         if (!IsOnSurface()) return NULL;
    3025 
    3026         /*Call Tria function*/
    3027         Tria* tria=(Tria*)SpawnTria(3,4,5); //nodes 3, 4 and 5 make the new tria (upper face).
    3028         ElementVector* pe=tria->CreatePVectorAdjointHoriz();
    3029         delete tria->matice; delete tria;
    3030 
    3031         /*clean up and return*/
    3032         return pe;
    3033 }
    3034 /*}}}*/
    3035 /*FUNCTION Penta::CreatePVectorAdjointStokes{{{1*/
    3036 ElementVector* Penta::CreatePVectorAdjointStokes(void){
    3037 
    3038         if (!IsOnSurface()) return NULL;
    3039 
    3040         /*Call Tria function*/
    3041         Tria* tria=(Tria*)SpawnTria(3,4,5); //nodes 3, 4 and 5 make the new tria (upper face).
    3042         ElementVector* pe=tria->CreatePVectorAdjointStokes();
    3043         delete tria->matice; delete tria;
    3044 
    3045         /*clean up and return*/
    3046         return pe;
    3047 }
    3048 /*}}}*/
    3049 /*FUNCTION Penta::Gradj {{{1*/
    3050 void  Penta::Gradj(Vec gradient,int control_type){
    3051         /*dJ/dalpha = ∂L/∂alpha = ∂J/∂alpha + ∂/∂alpha(KU-F)*/
    3052 
    3053         int              i,approximation;
    3054         Tria*            tria=NULL;
    3055 
    3056         /*If on water, skip grad (=0): */
    3057         if(IsOnWater())return;
    3058 
    3059         /*First deal with ∂/∂alpha(KU-F)*/
    3060         switch(control_type){
    3061 
    3062                 case FrictionCoefficientEnum:
    3063                         inputs->GetParameterValue(&approximation,ApproximationEnum);
    3064                         switch(approximation){
    3065                                 case MacAyealApproximationEnum:
    3066                                         GradjDragMacAyeal(gradient);
    3067                                         break;
    3068                                 case PattynApproximationEnum:
    3069                                         GradjDragPattyn(gradient);
    3070                                         break;
    3071                                 case StokesApproximationEnum:
    3072                                         GradjDragStokes(gradient);
    3073                                         break;
    3074                                 case NoneApproximationEnum:
    3075                                         /*Gradient is 0*/
    3076                                         break;
    3077                                 default:
    3078                                         _error_("approximation %s not supported yet",EnumToStringx(approximation));
    3079                         }
    3080                         break;
    3081 
    3082                 case MaterialsRheologyBbarEnum:
    3083                         inputs->GetParameterValue(&approximation,ApproximationEnum);
    3084                         switch(approximation){
    3085                                 case MacAyealApproximationEnum:
    3086                                         GradjBbarMacAyeal(gradient);
    3087                                         break;
    3088                                 case PattynApproximationEnum:
    3089                                         GradjBbarPattyn(gradient);
    3090                                         break;
    3091                                 case StokesApproximationEnum:
    3092                                         GradjBbarStokes(gradient);
    3093                                         break;
    3094                                 case NoneApproximationEnum:
    3095                                         /*Gradient is 0*/
    3096                                         break;
    3097                                 default:
    3098                                         _error_("approximation %s not supported yet",EnumToStringx(approximation));
    3099                         }
    3100                         break;
    3101 
    3102                 default:
    3103                         _error_("control type %s not supported yet: ",EnumToStringx(control_type));
    3104         }
    3105 
    3106         /*Now deal with ∂J/∂alpha*/
    3107         int        *responses = NULL;
    3108         int         num_responses,resp;
    3109         this->parameters->FindParam(&num_responses,InversionNumCostFunctionsEnum);
    3110         this->parameters->FindParam(&responses,NULL,NULL,StepResponsesEnum);
    3111 
    3112         for(resp=0;resp<num_responses;resp++) switch(responses[resp]){
    3113 
    3114                 case ThicknessAbsMisfitEnum:
    3115                 case SurfaceAbsVelMisfitEnum:
    3116                 case SurfaceRelVelMisfitEnum:
    3117                 case SurfaceLogVelMisfitEnum:
    3118                 case SurfaceLogVxVyMisfitEnum:
    3119                 case SurfaceAverageVelMisfitEnum:
    3120                         /*Nothing, J does not depends on the parameter being inverted for*/
    3121                         break;
    3122                 case DragCoefficientAbsGradientEnum:
    3123                         if (!IsOnBed()) return;
    3124                         tria=(Tria*)SpawnTria(0,1,2); //nodes 0, 1 and 2 make the new tria.
    3125                         tria->GradjDragGradient(gradient,resp);
    3126                         delete tria->matice; delete tria;
    3127                         break;
    3128                 case RheologyBbarAbsGradientEnum:
    3129                         if (!IsOnBed()) return;
    3130                         tria=(Tria*)SpawnTria(0,1,2); //nodes 0, 1 and 2 make the new tria.
    3131                         tria->GradjBGradient(gradient,resp);
    3132                         delete tria->matice; delete tria;
    3133                         break;
    3134                 default:
    3135                         _error_("response %s not supported yet",EnumToStringx(responses[resp]));
    3136         }
    3137         xfree((void**)&responses);
    3138 }
    3139 /*}}}*/
    3140 /*FUNCTION Penta::GradjDragMacAyeal {{{1*/
    3141 void  Penta::GradjDragMacAyeal(Vec gradient){
    3142 
    3143         /*Gradient is 0 if on shelf or not on bed*/
    3144         if(IsOnShelf() || !IsOnBed()) return;
    3145 
    3146         /*Spawn tria*/
    3147         Tria* tria=(Tria*)SpawnTria(0,1,2); //nodes 0, 1 and 2 make the new tria.
    3148         tria->GradjDragMacAyeal(gradient);
    3149         delete tria->matice; delete tria;
    3150 
    3151 } /*}}}*/
    3152 /*FUNCTION Penta::GradjDragPattyn {{{1*/
    3153 void  Penta::GradjDragPattyn(Vec gradient){
    3154 
    3155         int        i,j,ig;
    3156         int        analysis_type;
    3157         int        doflist1[NUMVERTICES];
    3158         double     vx,vy,lambda,mu,alpha_complement,Jdet;
    3159         double     bed,thickness,Neff,drag;
    3160         double     xyz_list[NUMVERTICES][3];
    3161         double     xyz_list_tria[NUMVERTICES2D][3]={0.0};
    3162         double     dk[NDOF3];
    3163         double     grade_g[NUMVERTICES]={0.0};
    3164         double     grade_g_gaussian[NUMVERTICES];
    3165         double     basis[6];
    3166         Friction*  friction=NULL;
    3167         GaussPenta  *gauss=NULL;
    3168 
    3169         /*Gradient is 0 if on shelf or not on bed*/
    3170         if(IsOnShelf() || !IsOnBed()) return;
    3171 
    3172         /*Retrieve all inputs and parameters*/
    3173         parameters->FindParam(&analysis_type,AnalysisTypeEnum);
    3174         GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
    3175         for(i=0;i<NUMVERTICES2D;i++) for(j=0;j<2;j++) xyz_list_tria[i][j]=xyz_list[i][j];
    3176         GetDofList1(&doflist1[0]);
    3177         Input* adjointx_input=inputs->GetInput(AdjointxEnum);               _assert_(adjointx_input);
    3178         Input* adjointy_input=inputs->GetInput(AdjointyEnum);               _assert_(adjointy_input);
    3179         Input* vx_input=inputs->GetInput(VxEnum);                           _assert_(vx_input);
    3180         Input* vy_input=inputs->GetInput(VyEnum);                           _assert_(vy_input);
    3181         Input* dragcoefficient_input=inputs->GetInput(FrictionCoefficientEnum); _assert_(dragcoefficient_input);
    3182 
    3183         /*Build frictoin element, needed later: */
    3184         friction=new Friction("2d",inputs,matpar,analysis_type);
    3185 
    3186         /* Start  looping on the number of gaussian points: */
    3187         gauss=new GaussPenta(0,1,2,4);
    3188         for (ig=gauss->begin();ig<gauss->end();ig++){
    3189 
    3190                 gauss->GaussPoint(ig);
    3191 
    3192                 GetTriaJacobianDeterminant(&Jdet, &xyz_list_tria[0][0],gauss);
    3193                 GetNodalFunctionsP1(basis, gauss);
    3194 
    3195                 /*Build alpha_complement_list: */
    3196                 friction->GetAlphaComplement(&alpha_complement, gauss,VxEnum,VyEnum,VzEnum);
    3197 
    3198                 dragcoefficient_input->GetParameterValue(&drag, gauss);
    3199                 adjointx_input->GetParameterValue(&lambda, gauss);
    3200                 adjointy_input->GetParameterValue(&mu, gauss);
    3201                 vx_input->GetParameterValue(&vx,gauss);
    3202                 vy_input->GetParameterValue(&vy,gauss);
    3203                 dragcoefficient_input->GetParameterDerivativeValue(&dk[0],&xyz_list[0][0],gauss);
    3204 
    3205                 /*Build gradje_g_gaussian vector (actually -dJ/ddrag): */
    3206                 for (i=0;i<NUMVERTICES;i++){
    3207                         grade_g_gaussian[i]=-2*drag*alpha_complement*((lambda*vx+mu*vy))*Jdet*gauss->weight*basis[i]; /*basis are 0 for the 3 upper nodes*/
    3208                 }
    3209 
    3210                 /*Add gradje_g_gaussian vector to gradje_g: */
    3211                 for(i=0;i<NUMVERTICES;i++){
    3212                         _assert_(!isnan(grade_g[i]));
    3213                         grade_g[i]+=grade_g_gaussian[i];
    3214                 }
    3215         }
    3216         VecSetValues(gradient,NUMVERTICES,doflist1,(const double*)grade_g,ADD_VALUES);
    3217 
    3218         /*Clean up and return*/
    3219         delete gauss;
    3220         delete friction;
    3221 }
    3222 /*}}}*/
    3223 /*FUNCTION Penta::GradjDragStokes {{{1*/
    3224 void  Penta::GradjDragStokes(Vec gradient){
    3225 
    3226         int        i,j,ig;
    3227         int        analysis_type;
    3228         int        doflist1[NUMVERTICES];
    3229         double     bed,thickness,Neff;
    3230         double     lambda,mu,xi,Jdet,vx,vy,vz;
    3231         double     alpha_complement,drag;
    3232         double     surface_normal[3],bed_normal[3];
    3233         double     xyz_list[NUMVERTICES][3];
    3234         double     xyz_list_tria[NUMVERTICES2D][3]={0.0};
    3235         double     dk[NDOF3];
    3236         double     basis[6];
    3237         double     grade_g[NUMVERTICES]={0.0};
    3238         double     grade_g_gaussian[NUMVERTICES];
    3239         Friction*  friction=NULL;
    3240         GaussPenta* gauss=NULL;
    3241 
    3242         /*Gradient is 0 if on shelf or not on bed*/
    3243         if(IsOnShelf() || !IsOnBed()) return;
    3244 
    3245         /*Retrieve all inputs and parameters*/
    3246         parameters->FindParam(&analysis_type,AnalysisTypeEnum);
    3247         GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
    3248         for(i=0;i<NUMVERTICES2D;i++) for(j=0;j<2;j++) xyz_list_tria[i][j]=xyz_list[i][j];
    3249         GetDofList1(&doflist1[0]);
    3250         Input* drag_input    =inputs->GetInput(FrictionCoefficientEnum); _assert_(drag_input);
    3251         Input* vx_input      =inputs->GetInput(VxEnum);              _assert_(vx_input);
    3252         Input* vy_input      =inputs->GetInput(VyEnum);              _assert_(vy_input);
    3253         Input* vz_input      =inputs->GetInput(VzEnum);              _assert_(vz_input);
    3254         Input* adjointx_input=inputs->GetInput(AdjointxEnum);        _assert_(adjointx_input);
    3255         Input* adjointy_input=inputs->GetInput(AdjointyEnum);        _assert_(adjointy_input);
    3256         Input* adjointz_input=inputs->GetInput(AdjointzEnum);        _assert_(adjointz_input);
    3257 
    3258         /*Build frictoin element, needed later: */
    3259         friction=new Friction("3d",inputs,matpar,analysis_type);
    3260 
    3261         /* Start  looping on the number of gaussian points: */
    3262         gauss=new GaussPenta(0,1,2,4);
    3263         for(ig=gauss->begin();ig<gauss->end();ig++){
    3264 
    3265                 gauss->GaussPoint(ig);
    3266 
    3267                 /*Recover alpha_complement and drag: */
    3268                 friction->GetAlphaComplement(&alpha_complement, gauss,VxEnum,VyEnum,VzEnum);
    3269                 drag_input->GetParameterValue(&drag,gauss);
    3270 
    3271                 /*recover lambda mu and xi: */
    3272                 adjointx_input->GetParameterValue(&lambda,gauss);
    3273                 adjointy_input->GetParameterValue(&mu    ,gauss);
    3274                 adjointz_input->GetParameterValue(&xi    ,gauss);
    3275 
    3276                 /*recover vx vy and vz: */
    3277                 vx_input->GetParameterValue(&vx, gauss);
    3278                 vy_input->GetParameterValue(&vy, gauss);
    3279                 vz_input->GetParameterValue(&vz, gauss);
    3280 
    3281                 /*Get normal vector to the bed */
    3282                 SurfaceNormal(&surface_normal[0],xyz_list_tria);
    3283 
    3284                 bed_normal[0]=-surface_normal[0]; //Function is for upper surface, so the normal to the bed is the opposite of the result
    3285                 bed_normal[1]=-surface_normal[1];
    3286                 bed_normal[2]=-surface_normal[2];
    3287 
    3288                 /* Get Jacobian determinant: */
    3289                 GetTriaJacobianDeterminant(&Jdet,&xyz_list_tria[0][0],gauss);
    3290                 GetNodalFunctionsP1(basis, gauss);
    3291 
    3292                 /*Get k derivative: dk/dx */
    3293                 drag_input->GetParameterDerivativeValue(&dk[0],&xyz_list[0][0],gauss);
    3294 
    3295                 /*Build gradje_g_gaussian vector (actually -dJ/ddrag): */
    3296                 for (i=0;i<NUMVERTICES;i++){
    3297                         //standard gradient dJ/dki
    3298                         grade_g_gaussian[i]=(
    3299                                                 -lambda*(2*drag*alpha_complement*(vx - vz*bed_normal[0]*bed_normal[2]))
    3300                                                 -mu    *(2*drag*alpha_complement*(vy - vz*bed_normal[1]*bed_normal[2]))
    3301                                                 -xi    *(2*drag*alpha_complement*(-vx*bed_normal[0]*bed_normal[2]-vy*bed_normal[1]*bed_normal[2]))
    3302                                                 )*Jdet*gauss->weight*basis[i];
    3303                 }
    3304 
    3305                 /*Add gradje_g_gaussian vector to gradje_g: */
    3306                 for( i=0; i<NUMVERTICES; i++)grade_g[i]+=grade_g_gaussian[i];
    3307         }
    3308 
    3309         VecSetValues(gradient,NUMVERTICES,doflist1,(const double*)grade_g,ADD_VALUES);
    3310 
    3311         delete friction;
    3312         delete gauss;
    3313 }
    3314 /*}}}*/
    3315 /*FUNCTION Penta::GradjBbarMacAyeal {{{1*/
    3316 void  Penta::GradjBbarMacAyeal(Vec gradient){
    3317 
    3318         /*This element should be collapsed into a tria element at its base*/
    3319         if (!IsOnBed()) return;
    3320 
    3321         /*Depth Average B*/
    3322         this->InputDepthAverageAtBase(MaterialsRheologyBEnum,MaterialsRheologyBbarEnum,MaterialsEnum);
    3323 
    3324         /*Collapse element to the base*/
    3325         Tria* tria=(Tria*)SpawnTria(0,1,2); //nodes 0, 1 and 2 make the new tria (lower face).
    3326         tria->GradjBMacAyeal(gradient);
    3327         delete tria->matice; delete tria;
    3328 
    3329         /*delete Average B*/
    3330         this->matice->inputs->DeleteInput(MaterialsRheologyBbarEnum);
    3331 
    3332 } /*}}}*/
    3333 /*FUNCTION Penta::GradjBbarPattyn {{{1*/
    3334 void  Penta::GradjBbarPattyn(Vec gradient){
    3335 
    3336         /*Gradient is computed on bed only (Bbar)*/
    3337         if (!IsOnBed()) return;
    3338 
    3339         /*Depth Average B*/
    3340         this->InputDepthAverageAtBase(MaterialsRheologyBEnum,MaterialsRheologyBbarEnum,MaterialsEnum);
    3341 
    3342         /*Collapse element to the base*/
    3343         Tria* tria=(Tria*)SpawnTria(0,1,2);
    3344         tria->GradjBMacAyeal(gradient);    //We use MacAyeal as an estimate for now
    3345         delete tria->matice; delete tria;
    3346 
    3347         /*delete Average B*/
    3348         this->matice->inputs->DeleteInput(MaterialsRheologyBbarEnum);
    3349 } /*}}}*/
    3350 /*FUNCTION Penta::GradjBbarStokes {{{1*/
    3351 void  Penta::GradjBbarStokes(Vec gradient){
    3352 
    3353         /*Gradient is computed on bed only (Bbar)*/
    3354         if (!IsOnBed()) return;
    3355 
    3356         /*Depth Average B*/
    3357         this->InputDepthAverageAtBase(MaterialsRheologyBEnum,MaterialsRheologyBbarEnum,MaterialsEnum);
    3358 
    3359         /*Collapse element to the base*/
    3360         Tria* tria=(Tria*)SpawnTria(0,1,2);
    3361         tria->GradjBMacAyeal(gradient);    //We use MacAyeal as an estimate for now
    3362         delete tria->matice; delete tria;
    3363 
    3364         /*delete Average B*/
    3365         this->matice->inputs->DeleteInput(MaterialsRheologyBbarEnum);
    3366 } /*}}}*/
    3367 /*FUNCTION Penta::InputControlUpdate{{{1*/
    3368 void  Penta::InputControlUpdate(double scalar,bool save_parameter){
    3369 
    3370         /*Intermediary*/
    3371         int    num_controls;
    3372         int*   control_type=NULL;
    3373         Input* input=NULL;
    3374 
    3375         /*retrieve some parameters: */
    3376         this->parameters->FindParam(&num_controls,InversionNumControlParametersEnum);
    3377         this->parameters->FindParam(&control_type,NULL,InversionControlParametersEnum);
    3378 
    3379         for(int i=0;i<num_controls;i++){
    3380 
    3381                 if(control_type[i]==MaterialsRheologyBbarEnum){
    3382                         if (!IsOnBed()) goto cleanup_and_return;
    3383                         input=(Input*)matice->inputs->GetInput(MaterialsRheologyBEnum); _assert_(input);
    3384                 }
    3385                 else{
    3386                         input=(Input*)this->inputs->GetInput(control_type[i]); _assert_(input);
    3387                 }
    3388 
    3389                 if (input->Enum()!=ControlInputEnum) _error_("input %s is not a ControlInput",EnumToStringx(control_type[i]));
    3390 
    3391                 ((ControlInput*)input)->UpdateValue(scalar);
    3392                 ((ControlInput*)input)->Constrain();
    3393                 if (save_parameter) ((ControlInput*)input)->SaveValue();
    3394 
    3395                 if(control_type[i]==MaterialsRheologyBbarEnum){
    3396                         this->InputExtrude(MaterialsRheologyBEnum,MaterialsEnum);
    3397                 }
    3398         }
    3399 
    3400         /*Clean up and return*/
    3401 cleanup_and_return:
    3402         xfree((void**)&control_type);
    3403 }
    3404 /*}}}*/
    3405 /*FUNCTION Penta::InputUpdateFromSolutionAdjointStokes {{{1*/
    3406 void  Penta::InputUpdateFromSolutionAdjointStokes(double* solution){
    3407 
    3408         const int    numdof=NDOF4*NUMVERTICES;
    3409 
    3410         int    i;
    3411         double values[numdof];
    3412         double lambdax[NUMVERTICES];
    3413         double lambday[NUMVERTICES];
    3414         double lambdaz[NUMVERTICES];
    3415         double lambdap[NUMVERTICES];
    3416         int*   doflist=NULL;
    3417 
    3418         /*Get dof list: */
    3419         GetDofList(&doflist,NoneApproximationEnum,GsetEnum);
    3420 
    3421         /*Use the dof list to index into the solution vector: */
    3422         for(i=0;i<numdof;i++) values[i]=solution[doflist[i]];
    3423 
    3424         /*Ok, we have vx and vy in values, fill in vx and vy arrays: */
    3425         for(i=0;i<NUMVERTICES;i++){
    3426                 lambdax[i]=values[i*NDOF4+0];
    3427                 lambday[i]=values[i*NDOF4+1];
    3428                 lambdaz[i]=values[i*NDOF4+2];
    3429                 lambdap[i]=values[i*NDOF4+3];
    3430 
    3431                 /*Check solution*/
    3432                 if(isnan(lambdax[i])) _error_("NaN found in solution vector");
    3433                 if(isnan(lambday[i])) _error_("NaN found in solution vector");
    3434                 if(isnan(lambdaz[i])) _error_("NaN found in solution vector");
    3435                 if(isnan(lambdap[i])) _error_("NaN found in solution vector");
    3436         }
    3437 
    3438         /*Add vx and vy as inputs to the tria element: */
    3439         this->inputs->AddInput(new PentaVertexInput(AdjointxEnum,lambdax));
    3440         this->inputs->AddInput(new PentaVertexInput(AdjointyEnum,lambday));
    3441         this->inputs->AddInput(new PentaVertexInput(AdjointzEnum,lambdaz));
    3442         this->inputs->AddInput(new PentaVertexInput(AdjointpEnum,lambdap));
    3443 
    3444         /*Free ressources:*/
    3445         xfree((void**)&doflist);
    3446 }
    3447 /*}}}*/
    3448 /*FUNCTION Penta::InputUpdateFromSolutionAdjointHoriz {{{1*/
    3449 void  Penta::InputUpdateFromSolutionAdjointHoriz(double* solution){
    3450 
    3451         const int numdof=NDOF2*NUMVERTICES;
    3452 
    3453         int    i;
    3454         double values[numdof];
    3455         double lambdax[NUMVERTICES];
    3456         double lambday[NUMVERTICES];
    3457         int*   doflist=NULL;
    3458 
    3459         /*Get dof list: */
    3460         GetDofList(&doflist,NoneApproximationEnum,GsetEnum);
    3461 
    3462         /*Use the dof list to index into the solution vector: */
    3463         for(i=0;i<numdof;i++) values[i]=solution[doflist[i]];
    3464 
    3465         /*Ok, we have vx and vy in values, fill in vx and vy arrays: */
    3466         for(i=0;i<NUMVERTICES;i++){
    3467                 lambdax[i]=values[i*NDOF2+0];
    3468                 lambday[i]=values[i*NDOF2+1];
    3469 
    3470                 /*Check solution*/
    3471                 if(isnan(lambdax[i]))       _error_("NaN found in solution vector");
    3472                 if(isnan(lambday[i]))       _error_("NaN found in solution vector");
    3473         }
    3474 
    3475         /*Add vx and vy as inputs to the tria element: */
    3476         this->inputs->AddInput(new PentaVertexInput(AdjointxEnum,lambdax));
    3477         this->inputs->AddInput(new PentaVertexInput(AdjointyEnum,lambday));
    3478 
    3479         /*Free ressources:*/
    3480         xfree((void**)&doflist);
    3481 }
    3482 /*}}}*/
    3483 /*FUNCTION Penta::SurfaceAverageVelMisfit {{{1*/
    3484 double Penta::SurfaceAverageVelMisfit(bool process_units,int weight_index){
    3485 
    3486         int    approximation;
    3487         double J;
    3488         Tria*  tria=NULL;
    3489 
    3490         /*retrieve inputs :*/
    3491         inputs->GetParameterValue(&approximation,ApproximationEnum);
    3492 
    3493         /*If on water, return 0: */
    3494         if(IsOnWater())return 0;
    3495 
    3496         /*Bail out if this element if:
    3497          * -> Non MacAyeal and not on the surface
    3498          * -> MacAyeal (2d model) and not on bed) */
    3499         if ((approximation!=MacAyealApproximationEnum && !IsOnSurface()) || (approximation==MacAyealApproximationEnum && !IsOnBed())){
    3500                 return 0;
    3501         }
    3502         else if (approximation==MacAyealApproximationEnum){
    3503 
    3504                 /*This element should be collapsed into a tria element at its base. Create this tria element,
    3505                  * and compute SurfaceAverageVelMisfit*/
    3506                 tria=(Tria*)SpawnTria(0,1,2); //nodes 0, 1 and 2 make the new tria (lower face).
    3507                 J=tria->SurfaceAverageVelMisfit(process_units,weight_index);
    3508                 delete tria->matice; delete tria;
    3509                 return J;
    3510         }
    3511         else{
    3512 
    3513                 tria=(Tria*)SpawnTria(3,4,5); //nodes 3, 4 and 5 make the new tria (upper face).
    3514                 J=tria->SurfaceAverageVelMisfit(process_units,weight_index);
    3515                 delete tria->matice; delete tria;
    3516                 return J;
    3517         }
    3518 }
    3519 /*}}}*/
    3520 /*FUNCTION Penta::SurfaceAbsVelMisfit {{{1*/
    3521 double Penta::SurfaceAbsVelMisfit(bool process_units,int weight_index){
    3522 
    3523         int    approximation;
    3524         double J;
    3525         Tria*  tria=NULL;
    3526 
    3527         /*retrieve inputs :*/
    3528         inputs->GetParameterValue(&approximation,ApproximationEnum);
    3529 
    3530         /*If on water, return 0: */
    3531         if(IsOnWater())return 0;
    3532 
    3533         /*Bail out if this element if:
    3534          * -> Non MacAyeal and not on the surface
    3535          * -> MacAyeal (2d model) and not on bed) */
    3536         if ((approximation!=MacAyealApproximationEnum && !IsOnSurface()) || (approximation==MacAyealApproximationEnum && !IsOnBed())){
    3537                 return 0;
    3538         }
    3539         else if (approximation==MacAyealApproximationEnum){
    3540 
    3541                 /*This element should be collapsed into a tria element at its base. Create this tria element,
    3542                  * and compute SurfaceAbsVelMisfit*/
    3543                 tria=(Tria*)SpawnTria(0,1,2); //nodes 0, 1 and 2 make the new tria (lower face).
    3544                 J=tria->SurfaceAbsVelMisfit(process_units,weight_index);
    3545                 delete tria->matice; delete tria;
    3546                 return J;
    3547         }
    3548         else{
    3549 
    3550                 tria=(Tria*)SpawnTria(3,4,5); //nodes 3, 4 and 5 make the new tria (upper face).
    3551                 J=tria->SurfaceAbsVelMisfit(process_units,weight_index);
    3552                 delete tria->matice; delete tria;
    3553                 return J;
    3554         }
    3555 }
    3556 /*}}}*/
    3557 /*FUNCTION Penta::SurfaceLogVelMisfit {{{1*/
    3558 double Penta::SurfaceLogVelMisfit(bool process_units,int weight_index){
    3559 
    3560         int    approximation;
    3561         double J;
    3562         Tria*  tria=NULL;
    3563 
    3564         /*retrieve inputs :*/
    3565         inputs->GetParameterValue(&approximation,ApproximationEnum);
    3566 
    3567         /*If on water, return 0: */
    3568         if(IsOnWater())return 0;
    3569 
    3570         /*Bail out if this element if:
    3571          * -> Non MacAyeal and not on the surface
    3572          * -> MacAyeal (2d model) and not on bed) */
    3573         if ((approximation!=MacAyealApproximationEnum && !IsOnSurface()) || (approximation==MacAyealApproximationEnum && !IsOnBed())){
    3574                 return 0;
    3575         }
    3576         else if (approximation==MacAyealApproximationEnum){
    3577 
    3578                 /*This element should be collapsed into a tria element at its base. Create this tria element,
    3579                  * and compute SurfaceLogVelMisfit*/
    3580                 tria=(Tria*)SpawnTria(0,1,2); //nodes 0, 1 and 2 make the new tria (lower face).
    3581                 J=tria->SurfaceLogVelMisfit(process_units,weight_index);
    3582                 delete tria->matice; delete tria;
    3583                 return J;
    3584         }
    3585         else{
    3586 
    3587                 tria=(Tria*)SpawnTria(3,4,5); //nodes 3, 4 and 5 make the new tria (upper face).
    3588                 J=tria->SurfaceLogVelMisfit(process_units,weight_index);
    3589                 delete tria->matice; delete tria;
    3590                 return J;
    3591         }
    3592 }
    3593 /*}}}*/
    3594 /*FUNCTION Penta::SurfaceLogVxVyMisfit {{{1*/
    3595 double Penta::SurfaceLogVxVyMisfit(bool process_units,int weight_index){
    3596 
    3597         double J;
    3598         Tria* tria=NULL;
    3599 
    3600         /*inputs: */
    3601         int  approximation;
    3602 
    3603         /*retrieve inputs :*/
    3604         inputs->GetParameterValue(&approximation,ApproximationEnum);
    3605 
    3606         /*If on water, return 0: */
    3607         if(IsOnWater())return 0;
    3608 
    3609         /*Bail out if this element if:
    3610          * -> Non MacAyeal and not on the surface
    3611          * -> MacAyeal (2d model) and not on bed) */
    3612         if ((approximation!=MacAyealApproximationEnum && !IsOnSurface()) || (approximation==MacAyealApproximationEnum && !IsOnBed())){
    3613                 return 0;
    3614         }
    3615         else if (approximation==MacAyealApproximationEnum){
    3616 
    3617                 /*This element should be collapsed into a tria element at its base. Create this tria element,
    3618                  * and compute SurfaceLogVxVyMisfit*/
    3619                 tria=(Tria*)SpawnTria(0,1,2); //nodes 0, 1 and 2 make the new tria (lower face).
    3620                 J=tria->SurfaceLogVxVyMisfit(process_units,weight_index);
    3621                 delete tria->matice; delete tria;
    3622                 return J;
    3623         }
    3624         else{
    3625 
    3626                 tria=(Tria*)SpawnTria(3,4,5); //nodes 3, 4 and 5 make the new tria (upper face).
    3627                 J=tria->SurfaceLogVxVyMisfit(process_units,weight_index);
    3628                 delete tria->matice; delete tria;
    3629                 return J;
    3630         }
    3631 }
    3632 /*}}}*/
    3633 /*FUNCTION Penta::SurfaceRelVelMisfit {{{1*/
    3634 double Penta::SurfaceRelVelMisfit(bool process_units,int weight_index){
    3635 
    3636         int    approximation;
    3637         double J;
    3638         Tria*  tria=NULL;
    3639 
    3640         /*retrieve inputs :*/
    3641         inputs->GetParameterValue(&approximation,ApproximationEnum);
    3642 
    3643         /*If on water, return 0: */
    3644         if(IsOnWater())return 0;
    3645 
    3646         /*Bail out if this element if:
    3647          * -> Non MacAyeal and not on the surface
    3648          * -> MacAyeal (2d model) and not on bed) */
    3649         if ((approximation!=MacAyealApproximationEnum && !IsOnSurface()) || (approximation==MacAyealApproximationEnum && !IsOnBed())){
    3650                 return 0;
    3651         }
    3652         else if (approximation==MacAyealApproximationEnum){
    3653 
    3654                 /*This element should be collapsed into a tria element at its base. Create this tria element,
    3655                  * and compute SurfaceRelVelMisfit*/
    3656                 tria=(Tria*)SpawnTria(0,1,2); //nodes 0, 1 and 2 make the new tria (lower face).
    3657                 J=tria->SurfaceRelVelMisfit(process_units,weight_index);
    3658                 delete tria->matice; delete tria;
    3659                 return J;
    3660         }
    3661         else{
    3662 
    3663                 tria=(Tria*)SpawnTria(3,4,5); //nodes 3, 4 and 5 make the new tria (upper face).
    3664                 J=tria->SurfaceRelVelMisfit(process_units,weight_index);
    3665                 delete tria->matice; delete tria;
    3666                 return J;
    3667         }
    3668 }
    3669 /*}}}*/
    3670 /*FUNCTION Penta::ThicknessAbsGradient{{{1*/
    3671 double Penta::ThicknessAbsGradient(bool process_units,int weight_index){
    3672 
    3673         _error_("Not implemented yet");
    3674 }
    3675 /*}}}*/
    3676 /*FUNCTION Penta::ThicknessAbsMisfit {{{1*/
    3677 double Penta::ThicknessAbsMisfit(bool process_units,int weight_index){
    3678 
    3679         int    approximation;
    3680         double J;
    3681         Tria*  tria=NULL;
    3682 
    3683         /*retrieve inputs :*/
    3684         inputs->GetParameterValue(&approximation,ApproximationEnum);
    3685 
    3686         /*If on water, return 0: */
    3687         if(IsOnWater())return 0;
    3688         _error_("Not implemented yet");
    3689 
    3690         tria=(Tria*)SpawnTria(0,1,2);
    3691         J=tria->ThicknessAbsMisfit(process_units,weight_index);
    3692         delete tria->matice; delete tria;
    3693         return J;
    3694 }
    3695 /*}}}*/
    3696 /*FUNCTION Penta::DragCoefficientAbsGradient{{{1*/
    3697 double Penta::DragCoefficientAbsGradient(bool process_units,int weight_index){
    3698 
    3699         double J;
    3700         Tria*  tria=NULL;
    3701 
    3702         /*If on water, on shelf or not on bed, skip: */
    3703         if(IsOnWater()|| IsOnShelf() || !IsOnBed()) return 0;
    3704 
    3705         tria=(Tria*)SpawnTria(0,1,2); //nodes 0, 1 and 2 make the new tria
    3706         J=tria->DragCoefficientAbsGradient(process_units,weight_index);
    3707         delete tria->matice; delete tria;
    3708         return J;
    3709 }
    3710 /*}}}*/
    3711 /*FUNCTION Penta::RheologyBbarAbsGradient{{{1*/
    3712 double Penta::RheologyBbarAbsGradient(bool process_units,int weight_index){
    3713 
    3714         double J;
    3715         Tria*  tria=NULL;
    3716 
    3717         /*If on water, on shelf or not on bed, skip: */
    3718         if(IsOnWater() || !IsOnBed()) return 0;
    3719 
    3720         tria=(Tria*)SpawnTria(0,1,2); //nodes 0, 1 and 2 make the new tria
    3721         J=tria->RheologyBbarAbsGradient(process_units,weight_index);
    3722         delete tria->matice; delete tria;
    3723         return J;
    3724 }
    3725 /*}}}*/
    3726 
    3727 #endif
    3728 
    3729 
    3730 #ifdef _HAVE_DAKOTA_
    3731 /*FUNCTION Penta::InputUpdateFromVectorDakota(double* vector, int name, int type);{{{1*/
    3732 void  Penta::InputUpdateFromVectorDakota(double* vector, int name, int type){
    3733        
    3734         int i,j;
    3735 
    3736         /*Check that name is an element input*/
    3737         if (!IsInput(name)) return;
    3738 
    3739         switch(type){
    3740 
    3741                 case VertexEnum:
    3742 
    3743                         /*New PentaVertexInput*/
    3744                         double values[6];
    3745 
    3746                         /*Get values on the 6 vertices*/
    3747                         for (i=0;i<6;i++){
    3748                                 values[i]=vector[this->nodes[i]->GetSidList()]; //careful, vector of values here is not parallel distributed, but serial distributed (from a serial Dakota core!)
    3749                         }
    3750 
    3751                         /*Branch on the specified type of update: */
    3752                         switch(name){
    3753                                 case ThicknessEnum:
    3754                                         /*Update thickness + surface: assume bed is constant. On ice shelves, takes hydrostatic equilibrium {{{2*/
    3755                                         double  thickness[6];
    3756                                         double  thickness_init[6];
    3757                                         double  hydrostatic_ratio[6];
    3758                                         double  surface[6];
    3759                                         double  bed[6];
    3760                                        
    3761                                         /*retrieve inputs: */
    3762                                         GetParameterListOnVertices(&thickness_init[0],ThicknessEnum);
    3763                                         GetParameterListOnVertices(&hydrostatic_ratio[0],GeometryHydrostaticRatioEnum);
    3764                                         GetParameterListOnVertices(&bed[0],BedEnum);
    3765                                         GetParameterListOnVertices(&surface[0],SurfaceEnum);
    3766 
    3767                                         /*build new thickness: */
    3768 //                                      for(j=0;j<6;j++)thickness[j]=values[j];
    3769 
    3770                                         /*build new bed and surface: */
    3771                                         if (this->IsOnShelf()){
    3772                                                 /*hydrostatic equilibrium: */
    3773                                                 double rho_ice,rho_water,di;
    3774                                                 rho_ice=this->matpar->GetRhoIce();
    3775                                                 rho_water=this->matpar->GetRhoWater();
    3776 
    3777                                                 di=rho_ice/rho_water;
    3778 
    3779                                                 /*build new thickness: */
    3780                                                 for (j=0; j<6; j++) {
    3781                                                 /*  for observed/interpolated/hydrostatic thickness, remove scaling from any hydrostatic thickness  */
    3782                                                         if     (hydrostatic_ratio[j] >= 0.)
    3783                                                                 thickness[j]=values[j]-(values[j]/thickness_init[j]-1.)*hydrostatic_ratio[j]*surface[j]/(1.-di);
    3784                                                 /*  for minimum thickness, don't scale  */
    3785                                                         else
    3786                                                                 thickness[j]=thickness_init[j];
    3787 
    3788                                                 /*  check the computed thickness and update bed  */
    3789                                                         if (thickness[j] < 0.)
    3790                                                                 thickness[j]=1./(1.-di);
    3791                                                         bed[j]=surface[j]-thickness[j];
    3792                                                 }
    3793 
    3794 //                                              for(j=0;j<6;j++){
    3795 //                                                      surface[j]=(1-di)*thickness[j];
    3796 //                                                      bed[j]=-di*thickness[j];
    3797 //                                              }
    3798                                         }
    3799                                         else{
    3800                                                 /*build new thickness: */
    3801                                                 for (j=0; j<6; j++) {
    3802                                                 /*  for observed thickness, use scaled value  */
    3803                                                         if(hydrostatic_ratio[j] >= 0.)
    3804                                                                 thickness[j]=values[j];
    3805                                                 /*  for minimum thickness, don't scale  */
    3806                                                         else
    3807                                                                 thickness[j]=thickness_init[j];
    3808                                                 }
    3809 
    3810                                                 /*update bed on grounded ice: */
    3811 //                                              for(j=0;j<6;j++)surface[j]=bed[j]+thickness[j];
    3812                                                 for(j=0;j<6;j++)bed[j]=surface[j]-thickness[j];
    3813                                         }
    3814 
    3815                                         /*Add new inputs: */
    3816                                         this->inputs->AddInput(new PentaVertexInput(ThicknessEnum,thickness));
    3817                                         this->inputs->AddInput(new PentaVertexInput(BedEnum,bed));
    3818                                         this->inputs->AddInput(new PentaVertexInput(SurfaceEnum,surface));
    3819 
    3820                                         /*}}}*/
    3821                                         break;
    3822                                 default:
    3823                                         this->inputs->AddInput(new PentaVertexInput(name,values));
    3824                         }
    3825                         break;
    3826 
    3827                 default:
    3828                         _error_("type %i (%s) not implemented yet",type,EnumToStringx(type));
    3829         }
    3830 
    3831 }
    3832 /*}}}*/
    3833 /*FUNCTION Penta::InputUpdateFromVectorDakota(int* vector, int name, int type);{{{1*/
    3834 void  Penta::InputUpdateFromVectorDakota(int* vector, int name, int type){
    3835         _error_(" not supported yet!");
    3836 }
    3837 /*}}}*/
    3838 /*FUNCTION Penta::InputUpdateFromVectorDakota(bool* vector, int name, int type);{{{1*/
    3839 void  Penta::InputUpdateFromVectorDakota(bool* vector, int name, int type){
    3840         _error_(" not supported yet!");
    3841 }
    3842 /*}}}*/
    3843 #endif
    3844 
    3845627/*FUNCTION Penta::CreatePVector {{{1*/
    3846628void  Penta::CreatePVector(Vec pf){
     
    3860642        /*Just branch to the correct element stiffness matrix generator, according to the type of analysis we are carrying out: */
    3861643        switch(analysis_type){
     644                #ifdef _HAVE_DIAGNOSTIC_
    3862645                case DiagnosticHorizAnalysisEnum:
    3863646                        pe=CreatePVectorDiagnosticHoriz();
    3864647                        break;
    3865                 #ifdef _HAVE_CONTROL_
    3866                 case AdjointHorizAnalysisEnum:
    3867                         pe=CreatePVectorAdjointHoriz();
    3868                         break;
    3869                 #endif
    3870648                case DiagnosticHutterAnalysisEnum:
    3871649                        pe=CreatePVectorDiagnosticHutter();
     
    3874652                        pe=CreatePVectorDiagnosticVert();
    3875653                        break;
    3876                 case BedSlopeXAnalysisEnum: case SurfaceSlopeXAnalysisEnum: case BedSlopeYAnalysisEnum: case SurfaceSlopeYAnalysisEnum:
    3877                         pe=CreatePVectorSlope();
     654                #endif
     655                #ifdef _HAVE_CONTROL_
     656                case AdjointHorizAnalysisEnum:
     657                        pe=CreatePVectorAdjointHoriz();
    3878658                        break;
    3879                 case PrognosticAnalysisEnum:
    3880                         pe=CreatePVectorPrognostic();
    3881                         break;
    3882                 case BalancethicknessAnalysisEnum:
    3883                         pe=CreatePVectorBalancethickness();
    3884                         break;
     659                #endif
    3885660                #ifdef _HAVE_THERMAL_
    3886661                case ThermalAnalysisEnum:
     
    3894669                        break;
    3895670                #endif
     671                case BedSlopeXAnalysisEnum: case SurfaceSlopeXAnalysisEnum: case BedSlopeYAnalysisEnum: case SurfaceSlopeYAnalysisEnum:
     672                        pe=CreatePVectorSlope();
     673                        break;
     674                case PrognosticAnalysisEnum:
     675                        pe=CreatePVectorPrognostic();
     676                        break;
     677                #ifdef _HAVE_BALANCED_
     678                case BalancethicknessAnalysisEnum:
     679                        pe=CreatePVectorBalancethickness();
     680                        break;
     681                #endif
    3896682                default:
    3897683                        _error_("analysis %i (%s) not supported yet",analysis_type,EnumToStringx(analysis_type));
     
    3903689                delete pe;
    3904690        }
    3905 }
    3906 /*}}}*/
    3907 /*FUNCTION Penta::CreatePVectorBalancethickness {{{1*/
    3908 ElementVector* Penta::CreatePVectorBalancethickness(void){
    3909 
    3910         if (!IsOnBed()) return NULL;
    3911 
    3912         /*Depth Averaging Vx and Vy*/
    3913         this->InputDepthAverageAtBase(VxEnum,VxAverageEnum);
    3914         this->InputDepthAverageAtBase(VyEnum,VyAverageEnum);
    3915 
    3916         /*Call Tria function*/
    3917         Tria* tria=(Tria*)SpawnTria(0,1,2); //nodes 0, 1 and 2 make the new tria.
    3918         ElementVector* pe=tria->CreatePVectorBalancethickness();
    3919         delete tria->matice; delete tria;
    3920 
    3921         /*Delete Vx and Vy averaged*/
    3922         this->inputs->DeleteInput(VxAverageEnum);
    3923         this->inputs->DeleteInput(VyAverageEnum);
    3924 
    3925         /*Clean up and return*/
    3926         return pe;
    3927 }
    3928 /*}}}*/
    3929 /*FUNCTION Penta::CreatePVectorCouplingMacAyealStokes {{{1*/
    3930 ElementVector* Penta::CreatePVectorCouplingMacAyealStokes(void){
    3931 
    3932         /*compute all load vectors for this element*/
    3933         ElementVector* pe1=CreatePVectorCouplingMacAyealStokesViscous();
    3934         ElementVector* pe2=CreatePVectorCouplingMacAyealStokesFriction();
    3935         ElementVector* pe =new ElementVector(pe1,pe2);
    3936 
    3937         /*clean-up and return*/
    3938         delete pe1;
    3939         delete pe2;
    3940         return pe;
    3941 }
    3942 /*}}}*/
    3943 /*FUNCTION Penta::CreatePVectorCouplingMacAyealStokesViscous {{{1*/
    3944 ElementVector* Penta::CreatePVectorCouplingMacAyealStokesViscous(void){
    3945 
    3946         /*Constants*/
    3947         const int   numdof=NUMVERTICES*NDOF4;
    3948 
    3949         /*Intermediaries */
    3950         int         i,j,ig;
    3951         int         approximation;
    3952         double      viscosity,Jdet;
    3953         double      stokesreconditioning;
    3954         double      epsilon[6]; /* epsilon=[exx,eyy,ezz,exy,exz,eyz];*/
    3955         double      dw[3];
    3956         double      xyz_list[NUMVERTICES][3];
    3957         double      basis[6]; //for the six nodes of the penta
    3958         double      dbasis[3][6]; //for the six nodes of the penta
    3959         GaussPenta *gauss=NULL;
    3960 
    3961         /*Initialize Element vector and return if necessary*/
    3962         inputs->GetParameterValue(&approximation,ApproximationEnum);
    3963         if(approximation!=MacAyealStokesApproximationEnum) return NULL;
    3964         ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters,StokesApproximationEnum);
    3965 
    3966         /*Retrieve all inputs and parameters*/
    3967         GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
    3968         this->parameters->FindParam(&stokesreconditioning,DiagnosticStokesreconditioningEnum);
    3969         Input* vx_input=inputs->GetInput(VxEnum);               _assert_(vx_input);
    3970         Input* vy_input=inputs->GetInput(VyEnum);               _assert_(vy_input);
    3971         Input* vz_input=inputs->GetInput(VzEnum);               _assert_(vz_input);
    3972         Input* vzmacayeal_input=inputs->GetInput(VzMacAyealEnum);   _assert_(vzmacayeal_input);
    3973 
    3974         /* Start  looping on the number of gaussian points: */
    3975         gauss=new GaussPenta(5,5);
    3976         for (ig=gauss->begin();ig<gauss->end();ig++){
    3977 
    3978                 gauss->GaussPoint(ig);
    3979 
    3980                 GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss);
    3981                 GetNodalFunctionsP1(&basis[0], gauss);
    3982                 GetNodalFunctionsP1Derivatives(&dbasis[0][0],&xyz_list[0][0], gauss);
    3983 
    3984                 vzmacayeal_input->GetParameterDerivativeValue(&dw[0],&xyz_list[0][0],gauss);
    3985 
    3986                 this->GetStrainRate3d(&epsilon[0],&xyz_list[0][0],gauss,vx_input,vy_input,vz_input);
    3987                 matice->GetViscosity3dStokes(&viscosity,&epsilon[0]);
    3988 
    3989                 for(i=0;i<NUMVERTICES;i++){
    3990                         pe->values[i*NDOF4+0]+=-Jdet*gauss->weight*viscosity*dw[0]*dbasis[2][i];
    3991                         pe->values[i*NDOF4+1]+=-Jdet*gauss->weight*viscosity*dw[1]*dbasis[2][i];
    3992                         pe->values[i*NDOF4+2]+=-Jdet*gauss->weight*viscosity*(dw[0]*dbasis[0][i]+dw[1]*dbasis[1][i]+2*dw[2]*dbasis[2][i]);
    3993                         pe->values[i*NDOF4+3]+=Jdet*gauss->weight*stokesreconditioning*dw[2]*basis[i];
    3994                 }
    3995         }
    3996 
    3997         /*Clean up and return*/
    3998         delete gauss;
    3999         return pe;
    4000 }
    4001 /*}}}*/
    4002 /*FUNCTION Penta::CreatePVectorCouplingMacAyealStokesFriction{{{1*/
    4003 ElementVector* Penta::CreatePVectorCouplingMacAyealStokesFriction(void){
    4004 
    4005         /*Constants*/
    4006         const int numdof=NUMVERTICES*NDOF4;
    4007 
    4008         /*Intermediaries*/
    4009         int         i,j,ig;
    4010         int         approximation,analysis_type;
    4011         double      Jdet,Jdet2d;
    4012         double      stokesreconditioning;
    4013         double     bed_normal[3];
    4014         double      epsilon[6]; /* epsilon=[exx,eyy,ezz,exy,exz,eyz];*/
    4015         double      viscosity, w, alpha2_gauss;
    4016         double      dw[3];
    4017         double     xyz_list_tria[NUMVERTICES2D][3];
    4018         double      xyz_list[NUMVERTICES][3];
    4019         double      basis[6]; //for the six nodes of the penta
    4020         Tria*       tria=NULL;
    4021         Friction*   friction=NULL;
    4022         GaussPenta  *gauss=NULL;
    4023 
    4024         /*Initialize Element vector and return if necessary*/
    4025         if(!IsOnBed() || IsOnShelf()) return NULL;
    4026         inputs->GetParameterValue(&approximation,ApproximationEnum);
    4027         if(approximation!=MacAyealStokesApproximationEnum) return NULL;
    4028         ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters,StokesApproximationEnum);
    4029 
    4030         /*Retrieve all inputs and parameters*/
    4031         GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
    4032         parameters->FindParam(&analysis_type,AnalysisTypeEnum);
    4033         this->parameters->FindParam(&stokesreconditioning,DiagnosticStokesreconditioningEnum);
    4034         Input* vx_input=inputs->GetInput(VxEnum);               _assert_(vx_input);
    4035         Input* vy_input=inputs->GetInput(VyEnum);               _assert_(vy_input);
    4036         Input* vz_input=inputs->GetInput(VzEnum);               _assert_(vz_input);
    4037         Input* vzmacayeal_input=inputs->GetInput(VzMacAyealEnum);   _assert_(vzmacayeal_input);
    4038 
    4039         for(i=0;i<NUMVERTICES2D;i++) for(j=0;j<3;j++) xyz_list_tria[i][j]=xyz_list[i][j];
    4040 
    4041         /*build friction object, used later on: */
    4042         friction=new Friction("3d",inputs,matpar,analysis_type);
    4043 
    4044         /* Start looping on the number of gauss 2d (nodes on the bedrock) */
    4045         gauss=new GaussPenta(0,1,2,2);
    4046         for(ig=gauss->begin();ig<gauss->end();ig++){
    4047 
    4048                 gauss->GaussPoint(ig);
    4049 
    4050                 GetTriaJacobianDeterminant(&Jdet2d, &xyz_list_tria[0][0], gauss);
    4051                 GetNodalFunctionsP1(basis, gauss);
    4052 
    4053                 vzmacayeal_input->GetParameterValue(&w, gauss);
    4054                 vzmacayeal_input->GetParameterDerivativeValue(&dw[0],&xyz_list[0][0],gauss);
    4055 
    4056                 BedNormal(&bed_normal[0],xyz_list_tria);
    4057                 this->GetStrainRate3d(&epsilon[0],&xyz_list[0][0],gauss,vx_input,vy_input,vz_input);
    4058                 matice->GetViscosity3dStokes(&viscosity,&epsilon[0]);
    4059                 friction->GetAlpha2(&alpha2_gauss, gauss,VxEnum,VyEnum,VzEnum);
    4060 
    4061                 for(i=0;i<NUMVERTICES2D;i++){
    4062                         pe->values[i*NDOF4+0]+=Jdet2d*gauss->weight*(alpha2_gauss*w*bed_normal[0]*bed_normal[2]+2*viscosity*dw[2]*bed_normal[0])*basis[i];
    4063                         pe->values[i*NDOF4+1]+=Jdet2d*gauss->weight*(alpha2_gauss*w*bed_normal[1]*bed_normal[2]+2*viscosity*dw[2]*bed_normal[1])*basis[i];
    4064                         pe->values[i*NDOF4+2]+=Jdet2d*gauss->weight*2*viscosity*(dw[0]*bed_normal[0]+dw[1]*bed_normal[1]+dw[2]*bed_normal[2])*basis[i];
    4065                 }
    4066         }
    4067 
    4068         /*Clean up and return*/
    4069         delete gauss;
    4070         delete friction;
    4071         return pe;
    4072 }
    4073 /*}}}*/
    4074 /*FUNCTION Penta::CreatePVectorCouplingPattynStokes {{{1*/
    4075 ElementVector* Penta::CreatePVectorCouplingPattynStokes(void){
    4076 
    4077         /*compute all load vectors for this element*/
    4078         ElementVector* pe1=CreatePVectorCouplingPattynStokesViscous();
    4079         ElementVector* pe2=CreatePVectorCouplingPattynStokesFriction();
    4080         ElementVector* pe =new ElementVector(pe1,pe2);
    4081 
    4082         /*clean-up and return*/
    4083         delete pe1;
    4084         delete pe2;
    4085         return pe;
    4086 }
    4087 /*}}}*/
    4088 /*FUNCTION Penta::CreatePVectorCouplingPattynStokesViscous {{{1*/
    4089 ElementVector* Penta::CreatePVectorCouplingPattynStokesViscous(void){
    4090 
    4091         /*Constants*/
    4092         const int   numdof=NUMVERTICES*NDOF4;
    4093 
    4094         /*Intermediaries */
    4095         int         i,j,ig;
    4096         int         approximation;
    4097         double      viscosity,Jdet;
    4098         double      stokesreconditioning;
    4099         double      epsilon[6]; /* epsilon=[exx,eyy,ezz,exy,exz,eyz];*/
    4100         double      dw[3];
    4101         double      xyz_list[NUMVERTICES][3];
    4102         double      basis[6]; //for the six nodes of the penta
    4103         double      dbasis[3][6]; //for the six nodes of the penta
    4104         GaussPenta *gauss=NULL;
    4105 
    4106         /*Initialize Element vector and return if necessary*/
    4107         inputs->GetParameterValue(&approximation,ApproximationEnum);
    4108         if(approximation!=PattynStokesApproximationEnum) return NULL;
    4109         ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters,StokesApproximationEnum);
    4110 
    4111         /*Retrieve all inputs and parameters*/
    4112         GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
    4113         this->parameters->FindParam(&stokesreconditioning,DiagnosticStokesreconditioningEnum);
    4114         Input* vx_input=inputs->GetInput(VxEnum);               _assert_(vx_input);
    4115         Input* vy_input=inputs->GetInput(VyEnum);               _assert_(vy_input);
    4116         Input* vz_input=inputs->GetInput(VzEnum);               _assert_(vz_input);
    4117         Input* vzpattyn_input=inputs->GetInput(VzPattynEnum);   _assert_(vzpattyn_input);
    4118 
    4119         /* Start  looping on the number of gaussian points: */
    4120         gauss=new GaussPenta(5,5);
    4121         for (ig=gauss->begin();ig<gauss->end();ig++){
    4122 
    4123                 gauss->GaussPoint(ig);
    4124 
    4125                 GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss);
    4126                 GetNodalFunctionsP1(&basis[0], gauss);
    4127                 GetNodalFunctionsP1Derivatives(&dbasis[0][0],&xyz_list[0][0], gauss);
    4128 
    4129                 vzpattyn_input->GetParameterDerivativeValue(&dw[0],&xyz_list[0][0],gauss);
    4130 
    4131                 this->GetStrainRate3d(&epsilon[0],&xyz_list[0][0],gauss,vx_input,vy_input,vz_input);
    4132                 matice->GetViscosity3dStokes(&viscosity,&epsilon[0]);
    4133 
    4134                 for(i=0;i<NUMVERTICES;i++){
    4135                         pe->values[i*NDOF4+0]+=-Jdet*gauss->weight*viscosity*dw[0]*dbasis[2][i];
    4136                         pe->values[i*NDOF4+1]+=-Jdet*gauss->weight*viscosity*dw[1]*dbasis[2][i];
    4137                         pe->values[i*NDOF4+2]+=-Jdet*gauss->weight*viscosity*(dw[0]*dbasis[0][i]+dw[1]*dbasis[1][i]+2*dw[2]*dbasis[2][i]);
    4138                         pe->values[i*NDOF4+3]+=Jdet*gauss->weight*stokesreconditioning*dw[2]*basis[i];
    4139                 }
    4140         }
    4141 
    4142         /*Clean up and return*/
    4143         delete gauss;
    4144         return pe;
    4145 }
    4146 /*}}}*/
    4147 /*FUNCTION Penta::CreatePVectorCouplingPattynStokesFriction{{{1*/
    4148 ElementVector* Penta::CreatePVectorCouplingPattynStokesFriction(void){
    4149 
    4150         /*Constants*/
    4151         const int numdof=NUMVERTICES*NDOF4;
    4152 
    4153         /*Intermediaries*/
    4154         int         i,j,ig;
    4155         int         approximation,analysis_type;
    4156         double      Jdet,Jdet2d;
    4157         double      stokesreconditioning;
    4158         double     bed_normal[3];
    4159         double      epsilon[6]; /* epsilon=[exx,eyy,ezz,exy,exz,eyz];*/
    4160         double      viscosity, w, alpha2_gauss;
    4161         double      dw[3];
    4162         double     xyz_list_tria[NUMVERTICES2D][3];
    4163         double      xyz_list[NUMVERTICES][3];
    4164         double      basis[6]; //for the six nodes of the penta
    4165         Tria*       tria=NULL;
    4166         Friction*   friction=NULL;
    4167         GaussPenta  *gauss=NULL;
    4168 
    4169         /*Initialize Element vector and return if necessary*/
    4170         if(!IsOnBed() || IsOnShelf()) return NULL;
    4171         inputs->GetParameterValue(&approximation,ApproximationEnum);
    4172         if(approximation!=PattynStokesApproximationEnum) return NULL;
    4173         ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters,StokesApproximationEnum);
    4174 
    4175         /*Retrieve all inputs and parameters*/
    4176         GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
    4177         parameters->FindParam(&analysis_type,AnalysisTypeEnum);
    4178         this->parameters->FindParam(&stokesreconditioning,DiagnosticStokesreconditioningEnum);
    4179         Input* vx_input=inputs->GetInput(VxEnum);               _assert_(vx_input);
    4180         Input* vy_input=inputs->GetInput(VyEnum);               _assert_(vy_input);
    4181         Input* vz_input=inputs->GetInput(VzEnum);               _assert_(vz_input);
    4182         Input* vzpattyn_input=inputs->GetInput(VzPattynEnum);   _assert_(vzpattyn_input);
    4183 
    4184         for(i=0;i<NUMVERTICES2D;i++) for(j=0;j<3;j++) xyz_list_tria[i][j]=xyz_list[i][j];
    4185 
    4186         /*build friction object, used later on: */
    4187         friction=new Friction("3d",inputs,matpar,analysis_type);
    4188 
    4189         /* Start looping on the number of gauss 2d (nodes on the bedrock) */
    4190         gauss=new GaussPenta(0,1,2,2);
    4191         for(ig=gauss->begin();ig<gauss->end();ig++){
    4192 
    4193                 gauss->GaussPoint(ig);
    4194 
    4195                 GetTriaJacobianDeterminant(&Jdet2d, &xyz_list_tria[0][0], gauss);
    4196                 GetNodalFunctionsP1(basis, gauss);
    4197 
    4198                 vzpattyn_input->GetParameterValue(&w, gauss);
    4199                 vzpattyn_input->GetParameterDerivativeValue(&dw[0],&xyz_list[0][0],gauss);
    4200 
    4201                 BedNormal(&bed_normal[0],xyz_list_tria);
    4202                 this->GetStrainRate3d(&epsilon[0],&xyz_list[0][0],gauss,vx_input,vy_input,vz_input);
    4203                 matice->GetViscosity3dStokes(&viscosity,&epsilon[0]);
    4204                 friction->GetAlpha2(&alpha2_gauss, gauss,VxEnum,VyEnum,VzEnum);
    4205 
    4206                 for(i=0;i<NUMVERTICES2D;i++){
    4207                         pe->values[i*NDOF4+0]+=Jdet2d*gauss->weight*(alpha2_gauss*w*bed_normal[0]*bed_normal[2]+2*viscosity*dw[2]*bed_normal[0])*basis[i];
    4208                         pe->values[i*NDOF4+1]+=Jdet2d*gauss->weight*(alpha2_gauss*w*bed_normal[1]*bed_normal[2]+2*viscosity*dw[2]*bed_normal[1])*basis[i];
    4209                         pe->values[i*NDOF4+2]+=Jdet2d*gauss->weight*2*viscosity*(dw[0]*bed_normal[0]+dw[1]*bed_normal[1]+dw[2]*bed_normal[2])*basis[i];
    4210                 }
    4211         }
    4212 
    4213         /*Clean up and return*/
    4214         delete gauss;
    4215         delete friction;
    4216         return pe;
    4217 }
    4218 /*}}}*/
    4219 /*FUNCTION Penta::CreatePVectorDiagnosticHoriz{{{1*/
    4220 ElementVector* Penta::CreatePVectorDiagnosticHoriz(void){
    4221 
    4222         int approximation;
    4223         inputs->GetParameterValue(&approximation,ApproximationEnum);
    4224 
    4225         switch(approximation){
    4226                 case MacAyealApproximationEnum:
    4227                         return CreatePVectorDiagnosticMacAyeal();
    4228                 case PattynApproximationEnum:
    4229                         return CreatePVectorDiagnosticPattyn();
    4230                 case HutterApproximationEnum:
    4231                         return NULL;
    4232                 case NoneApproximationEnum:
    4233                         return NULL;
    4234                 case StokesApproximationEnum:
    4235                         return CreatePVectorDiagnosticStokes();
    4236                 case MacAyealPattynApproximationEnum:
    4237                         return CreatePVectorDiagnosticMacAyealPattyn();
    4238                 case MacAyealStokesApproximationEnum:
    4239                         return CreatePVectorDiagnosticMacAyealStokes();
    4240                 case PattynStokesApproximationEnum:
    4241                         return CreatePVectorDiagnosticPattynStokes();
    4242                 default:
    4243                         _error_("Approximation %s not supported yet",EnumToStringx(approximation));
    4244         }
    4245 }
    4246 /*}}}*/
    4247 /*FUNCTION Penta::CreatePVectorDiagnosticMacAyealPattyn{{{1*/
    4248 ElementVector* Penta::CreatePVectorDiagnosticMacAyealPattyn(void){
    4249 
    4250         /*compute all load vectors for this element*/
    4251         ElementVector* pe1=CreatePVectorDiagnosticMacAyeal();
    4252         ElementVector* pe2=CreatePVectorDiagnosticPattyn();
    4253         ElementVector* pe =new ElementVector(pe1,pe2);
    4254 
    4255         /*clean-up and return*/
    4256         delete pe1;
    4257         delete pe2;
    4258         return pe;
    4259 }
    4260 /*}}}*/
    4261 /*FUNCTION Penta::CreatePVectorDiagnosticMacAyealStokes{{{1*/
    4262 ElementVector* Penta::CreatePVectorDiagnosticMacAyealStokes(void){
    4263 
    4264         /*compute all load vectors for this element*/
    4265         ElementVector* pe1=CreatePVectorDiagnosticMacAyeal();
    4266         ElementVector* pe2=CreatePVectorDiagnosticStokes();
    4267         ElementVector* pe3=CreatePVectorCouplingMacAyealStokes();
    4268         ElementVector* pe =new ElementVector(pe1,pe2,pe3);
    4269 
    4270         /*clean-up and return*/
    4271         delete pe1;
    4272         delete pe2;
    4273         delete pe3;
    4274         return pe;
    4275 }
    4276 /*}}}*/
    4277 /*FUNCTION Penta::CreatePVectorDiagnosticPattynStokes{{{1*/
    4278 ElementVector* Penta::CreatePVectorDiagnosticPattynStokes(void){
    4279 
    4280         /*compute all load vectors for this element*/
    4281         ElementVector* pe1=CreatePVectorDiagnosticPattyn();
    4282         ElementVector* pe2=CreatePVectorDiagnosticStokes();
    4283         ElementVector* pe3=CreatePVectorCouplingPattynStokes();
    4284         ElementVector* pe =new ElementVector(pe1,pe2,pe3);
    4285 
    4286         /*clean-up and return*/
    4287         delete pe1;
    4288         delete pe2;
    4289         delete pe3;
    4290         return pe;
    4291 }
    4292 /*}}}*/
    4293 /*FUNCTION Penta::CreatePVectorDiagnosticHutter{{{1*/
    4294 ElementVector* Penta::CreatePVectorDiagnosticHutter(void){
    4295 
    4296         /*Constants*/
    4297         const int numdofs=NDOF2*NUMVERTICES;
    4298 
    4299         /*Intermediaries*/
    4300         int          i,j,k,ig;
    4301         int          node0,node1;
    4302         int          connectivity[2];
    4303         double       Jdet;
    4304         double       xyz_list[NUMVERTICES][3];
    4305         double       xyz_list_segment[2][3];
    4306         double       z_list[NUMVERTICES];
    4307         double       z_segment[2],slope[2];
    4308         double       slope2,constant_part;
    4309         double       rho_ice,gravity,n,B;
    4310         double       ub,vb,z_g,surface,thickness;
    4311         GaussPenta*  gauss=NULL;
    4312 
    4313         /*Initialize Element vector*/
    4314         ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters);
    4315 
    4316         /*Retrieve all inputs and parameters*/
    4317         GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
    4318         rho_ice=matpar->GetRhoIce();
    4319         gravity=matpar->GetG();
    4320         n=matice->GetN();
    4321         B=matice->GetB();
    4322         Input* thickness_input=inputs->GetInput(ThicknessEnum);  _assert_(thickness_input);
    4323         Input* surface_input=inputs->GetInput(SurfaceEnum);      _assert_(surface_input);
    4324         Input* slopex_input=inputs->GetInput(SurfaceSlopeXEnum); _assert_(slopex_input);
    4325         Input* slopey_input=inputs->GetInput(SurfaceSlopeYEnum); _assert_(slopey_input);
    4326         for(i=0;i<NUMVERTICES;i++)z_list[i]=xyz_list[i][2];
    4327 
    4328         /*Loop on the three segments*/
    4329         for(i=0;i<3;i++){
    4330                 node0=i;
    4331                 node1=i+3;
    4332 
    4333                 for(j=0;j<3;j++){
    4334                         xyz_list_segment[0][j]=xyz_list[node0][j];
    4335                         xyz_list_segment[1][j]=xyz_list[node1][j];
    4336                 }
    4337 
    4338                 connectivity[0]=nodes[node0]->GetConnectivity();
    4339                 connectivity[1]=nodes[node1]->GetConnectivity();
    4340 
    4341                 /*Loop on the Gauss points: */
    4342                 gauss=new GaussPenta(node0,node1,3);
    4343                 for(ig=gauss->begin();ig<gauss->end();ig++){
    4344                         gauss->GaussPoint(ig);
    4345 
    4346                         slopex_input->GetParameterValue(&slope[0],gauss);
    4347                         slopey_input->GetParameterValue(&slope[1],gauss);
    4348                         surface_input->GetParameterValue(&surface,gauss);
    4349                         thickness_input->GetParameterValue(&thickness,gauss);
    4350 
    4351                         slope2=pow(slope[0],2)+pow(slope[1],2);
    4352                         constant_part=-2*pow(rho_ice*gravity,n)*pow(slope2,((n-1)/2));
    4353 
    4354                         PentaRef::GetParameterValue(&z_g,&z_list[0],gauss);
    4355                         GetSegmentJacobianDeterminant(&Jdet,&xyz_list_segment[0][0],gauss);
    4356 
    4357                         if (IsOnSurface()){
    4358                                 for(j=0;j<NDOF2;j++) pe->values[2*node1+j]+=constant_part*pow((surface-z_g)/B,n)*slope[j]*Jdet*gauss->weight/(double)connectivity[1];
    4359                         }
    4360                         else{//connectivity is too large, should take only half on it
    4361                                 for(j=0;j<NDOF2;j++) pe->values[2*node1+j]+=constant_part*pow((surface-z_g)/B,n)*slope[j]*Jdet*gauss->weight*2/(double)connectivity[1];
    4362                         }
    4363                 }
    4364                 delete gauss;
    4365 
    4366                 //Deal with lower surface
    4367                 if (IsOnBed()){
    4368                         constant_part=-1.58*pow((double)10.0,-(double)10.0)*rho_ice*gravity*thickness;
    4369                         ub=constant_part*slope[0];
    4370                         vb=constant_part*slope[1];
    4371 
    4372                         pe->values[2*node0]+=ub/(double)connectivity[0];
    4373                         pe->values[2*node0+1]+=vb/(double)connectivity[0];
    4374                 }
    4375         }
    4376 
    4377         /*Clean up and return*/
    4378         return pe;
    4379 }
    4380 /*}}}*/
    4381 /*FUNCTION Penta::CreatePVectorDiagnosticMacAyeal{{{1*/
    4382 ElementVector* Penta::CreatePVectorDiagnosticMacAyeal(void){
    4383 
    4384         if (!IsOnBed()) return NULL;
    4385 
    4386         /*Call Tria function*/
    4387         Tria* tria=(Tria*)SpawnTria(0,1,2); //nodes 0, 1 and 2 make the new tria.
    4388         ElementVector* pe=tria->CreatePVectorDiagnosticMacAyeal();
    4389         delete tria->matice; delete tria;
    4390 
    4391         /*Clean up and return*/
    4392         return pe;
    4393 }
    4394 /*}}}*/
    4395 /*FUNCTION Penta::CreatePVectorDiagnosticPattyn{{{1*/
    4396 ElementVector* Penta::CreatePVectorDiagnosticPattyn(void){
    4397 
    4398         /*Constants*/
    4399         const int    numdof=NDOF2*NUMVERTICES;
    4400 
    4401         /*Intermediaries*/
    4402         int         i,j,ig;
    4403         double      Jdet;
    4404         double      slope[3]; //do not put 2! this goes into GetParameterDerivativeValue, which addresses slope[3] also!
    4405         double      driving_stress_baseline,thickness;
    4406         double      xyz_list[NUMVERTICES][3];
    4407         double      basis[6];
    4408         GaussPenta  *gauss=NULL;
    4409 
    4410         /*Initialize Element vector*/
    4411         ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters,PattynApproximationEnum);
    4412 
    4413         /*Retrieve all inputs and parameters*/
    4414         GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
    4415         Input* thickness_input=inputs->GetInput(ThicknessEnum); _assert_(thickness_input);
    4416         Input* surface_input=inputs->GetInput(SurfaceEnum);     _assert_(surface_input);
    4417 
    4418         /* Start  looping on the number of gaussian points: */
    4419         gauss=new GaussPenta(2,3);
    4420         for (ig=gauss->begin();ig<gauss->end();ig++){
    4421 
    4422                 gauss->GaussPoint(ig);
    4423 
    4424                 GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss);
    4425                 GetNodalFunctionsP1(basis, gauss);
    4426 
    4427                 thickness_input->GetParameterValue(&thickness, gauss);
    4428                 surface_input->GetParameterDerivativeValue(&slope[0],&xyz_list[0][0],gauss);
    4429 
    4430                 driving_stress_baseline=matpar->GetRhoIce()*matpar->GetG();
    4431 
    4432                 for(i=0;i<NUMVERTICES;i++) for(j=0;j<NDOF2;j++) pe->values[i*NDOF2+j]+= -driving_stress_baseline*slope[j]*Jdet*gauss->weight*basis[i];
    4433         }
    4434 
    4435         /*Clean up and return*/
    4436         delete gauss;
    4437         return pe;
    4438 }
    4439 /*}}}*/
    4440 /*FUNCTION Penta::CreatePVectorDiagnosticStokes {{{1*/
    4441 ElementVector* Penta::CreatePVectorDiagnosticStokes(void){
    4442 
    4443         /*compute all load vectors for this element*/
    4444         ElementVector* pe1=CreatePVectorDiagnosticStokesViscous();
    4445         ElementVector* pe2=CreatePVectorDiagnosticStokesShelf();
    4446         ElementVector* pe =new ElementVector(pe1,pe2);
    4447 
    4448         /*clean-up and return*/
    4449         delete pe1;
    4450         delete pe2;
    4451         return pe;
    4452 }
    4453 /*}}}*/
    4454 /*FUNCTION Penta::CreatePVectorDiagnosticStokesViscous {{{1*/
    4455 ElementVector* Penta::CreatePVectorDiagnosticStokesViscous(void){
    4456 
    4457         /*Constants*/
    4458         const int numdofbubble=NDOF4*NUMVERTICES+NDOF3*1;
    4459 
    4460         /*Intermediaries*/
    4461         int        i,j,ig;
    4462         int        approximation;
    4463         double     Jdet,viscosity;
    4464         double     gravity,rho_ice,stokesreconditioning;
    4465         double     xyz_list[NUMVERTICES][3];
    4466         double     epsilon[6]; /* epsilon=[exx,eyy,ezz,exy,exz,eyz];*/
    4467         double     l1l7[7]; //for the six nodes and the bubble
    4468         double     B[8][numdofbubble];
    4469         double     B_prime[8][numdofbubble];
    4470         double     B_prime_bubble[8][3];
    4471         double     D[8][8]={0.0};
    4472         double     D_scalar;
    4473         double     Pe_gaussian[numdofbubble]={0.0}; //for the six nodes and the bubble
    4474         double     Ke_temp[numdofbubble][3]={0.0}; //for the six nodes and the bubble
    4475         double     Ke_gaussian[numdofbubble][3];
    4476         GaussPenta *gauss=NULL;
    4477 
    4478         /*Initialize Element vector and return if necessary*/
    4479         inputs->GetParameterValue(&approximation,ApproximationEnum);
    4480         if(approximation!=StokesApproximationEnum && approximation!=MacAyealStokesApproximationEnum && approximation!=PattynStokesApproximationEnum) return NULL;
    4481         ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters,StokesApproximationEnum);
    4482 
    4483         /*Retrieve all inputs and parameters*/
    4484         this->parameters->FindParam(&stokesreconditioning,DiagnosticStokesreconditioningEnum);
    4485         rho_ice=matpar->GetRhoIce();
    4486         gravity=matpar->GetG();
    4487         GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
    4488         Input* vx_input=inputs->GetInput(VxEnum);   _assert_(vx_input);
    4489         Input* vy_input=inputs->GetInput(VyEnum);   _assert_(vy_input);
    4490         Input* vz_input=inputs->GetInput(VzEnum);   _assert_(vz_input);
    4491 
    4492         /* Start  looping on the number of gaussian points: */
    4493         gauss=new GaussPenta(5,5);
    4494         for (ig=gauss->begin();ig<gauss->end();ig++){
    4495 
    4496                 gauss->GaussPoint(ig);
    4497 
    4498                 GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss);
    4499                 GetBStokes(&B[0][0],&xyz_list[0][0],gauss);
    4500                 GetBprimeStokes(&B_prime[0][0],&xyz_list[0][0], gauss);
    4501                 GetNodalFunctionsMINI(&l1l7[0], gauss);
    4502 
    4503                 this->GetStrainRate3d(&epsilon[0],&xyz_list[0][0],gauss,vx_input,vy_input,vz_input);
    4504                 matice->GetViscosity3dStokes(&viscosity,&epsilon[0]);
    4505 
    4506                 for(i=0;i<NUMVERTICES+1;i++){
    4507                         Pe_gaussian[i*NDOF4+2]+=-rho_ice*gravity*Jdet*gauss->weight*l1l7[i];
    4508                 }
    4509 
    4510                 /*Get bubble part of Bprime */
    4511                 for(i=0;i<8;i++) for(j=0;j<3;j++) B_prime_bubble[i][j]=B_prime[i][j+24];
    4512 
    4513                 D_scalar=gauss->weight*Jdet;
    4514                 for (i=0;i<6;i++) D[i][i]=D_scalar*2*viscosity;
    4515                 for (i=6;i<8;i++) D[i][i]=-D_scalar*stokesreconditioning;
    4516 
    4517                 TripleMultiply(&B[0][0],8,numdofbubble,1,
    4518                                         &D[0][0],8,8,0,
    4519                                         &B_prime_bubble[0][0],8,3,0,
    4520                                         &Ke_gaussian[0][0],0);
    4521 
    4522                 for(i=0;i<numdofbubble;i++) for(j=0;j<NDOF3;j++) Ke_temp[i][j]+=Ke_gaussian[i][j];
    4523         }
    4524 
    4525         /*Condensation*/
    4526         ReduceVectorStokes(pe->values, &Ke_temp[0][0], &Pe_gaussian[0]);
    4527 
    4528         /*Clean up and return*/
    4529         delete gauss;
    4530         return pe;
    4531 }
    4532 /*}}}*/
    4533 /*FUNCTION Penta::CreatePVectorDiagnosticStokesShelf{{{1*/
    4534 ElementVector* Penta::CreatePVectorDiagnosticStokesShelf(void){
    4535 
    4536         /*Intermediaries*/
    4537         int         i,j,ig;
    4538         int         approximation,shelf_dampening;
    4539         double      gravity,rho_water,bed,water_pressure;
    4540         double      damper,normal_vel,vx,vy,vz,dt;
    4541         double          xyz_list_tria[NUMVERTICES2D][3];
    4542         double      xyz_list[NUMVERTICES][3];
    4543         double          bed_normal[3];
    4544         double      dz[3];
    4545         double      basis[6]; //for the six nodes of the penta
    4546         double      Jdet2d;
    4547         GaussPenta  *gauss=NULL;
    4548 
    4549         /*Initialize Element vector and return if necessary*/
    4550         if(!IsOnBed() || !IsOnShelf()) return NULL;
    4551         inputs->GetParameterValue(&approximation,ApproximationEnum);
    4552         this->parameters->FindParam(&shelf_dampening,DiagnosticShelfDampeningEnum);
    4553         if(approximation!=StokesApproximationEnum && approximation!=MacAyealStokesApproximationEnum && approximation!=PattynStokesApproximationEnum) return NULL;
    4554         ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters,StokesApproximationEnum);
    4555 
    4556         /*Retrieve all inputs and parameters*/
    4557         rho_water=matpar->GetRhoWater();
    4558         gravity=matpar->GetG();
    4559         GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
    4560         Input* bed_input=inputs->GetInput(BedEnum); _assert_(bed_input);
    4561         Input* vx_input=inputs->GetInput(VxEnum);   _assert_(vx_input);
    4562         Input* vy_input=inputs->GetInput(VyEnum);   _assert_(vy_input);
    4563         Input* vz_input=inputs->GetInput(VzEnum);   _assert_(vz_input);
    4564 
    4565         for(i=0;i<NUMVERTICES2D;i++) for(j=0;j<3;j++) xyz_list_tria[i][j]=xyz_list[i][j];
    4566 
    4567         /* Start looping on the number of gauss 2d (nodes on the bedrock) */
    4568         gauss=new GaussPenta(0,1,2,2);
    4569         for(ig=gauss->begin();ig<gauss->end();ig++){
    4570 
    4571                 gauss->GaussPoint(ig);
    4572 
    4573                 GetTriaJacobianDeterminant(&Jdet2d, &xyz_list_tria[0][0], gauss);
    4574                 GetNodalFunctionsP1(basis, gauss);
    4575 
    4576                 BedNormal(&bed_normal[0],xyz_list_tria);
    4577                 bed_input->GetParameterValue(&bed, gauss);
    4578                 if(shelf_dampening){ //add dampening to avoid too high vertical velocities when not in hydrostatic equilibrium
    4579                         bed_input->GetParameterDerivativeValue(&dz[0],&xyz_list[0][0],gauss);
    4580                         vx_input->GetParameterValue(&vx, gauss);
    4581                         vy_input->GetParameterValue(&vy, gauss);
    4582                         vz_input->GetParameterValue(&vz, gauss);
    4583                         dt=0;
    4584                         normal_vel=bed_normal[0]*vx+bed_normal[1]*vy+bed_normal[2]*vz;
    4585                         damper=gravity*rho_water*pow(1+pow(dz[0],2)+pow(dz[1],2),0.5)*normal_vel*dt;
    4586                 }
    4587                 else damper=0;
    4588                 water_pressure=gravity*rho_water*bed;
    4589 
    4590                 for(i=0;i<NUMVERTICES;i++) for(j=0;j<3;j++) pe->values[i*NDOF4+j]+=(water_pressure+damper)*gauss->weight*Jdet2d*basis[i]*bed_normal[j];
    4591         }
    4592 
    4593         /*Clean up and return*/
    4594         delete gauss;
    4595         return pe;
    4596 }
    4597 /*}}}*/
    4598 /*FUNCTION Penta::CreatePVectorDiagnosticVert {{{1*/
    4599 ElementVector* Penta::CreatePVectorDiagnosticVert(void){
    4600 
    4601         /*compute all load vectors for this element*/
    4602         ElementVector* pe1=CreatePVectorDiagnosticVertVolume();
    4603         ElementVector* pe2=CreatePVectorDiagnosticVertBase();
    4604         ElementVector* pe =new ElementVector(pe1,pe2);
    4605 
    4606         /*clean-up and return*/
    4607         delete pe1;
    4608         delete pe2;
    4609         return pe;
    4610 }
    4611 /*}}}*/
    4612 /*FUNCTION Penta::CreatePVectorDiagnosticVertVolume {{{1*/
    4613 ElementVector* Penta::CreatePVectorDiagnosticVertVolume(void){
    4614 
    4615         /*Constants*/
    4616         const int  numdof=NDOF1*NUMVERTICES;
    4617 
    4618         /*Intermediaries*/
    4619         int        i,ig;
    4620         int        approximation;
    4621         double     Jdet;
    4622         double     xyz_list[NUMVERTICES][3];
    4623         double     dudx,dvdy,dwdz;
    4624         double     du[3],dv[3],dw[3];
    4625         double     basis[6];
    4626         GaussPenta *gauss=NULL;
    4627 
    4628         /*Initialize Element vector*/
    4629         ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters);
    4630 
    4631         /*Retrieve all inputs and parameters*/
    4632         GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
    4633         inputs->GetParameterValue(&approximation,ApproximationEnum);
    4634         Input* vx_input=inputs->GetInput(VxEnum); _assert_(vx_input);
    4635         Input* vy_input=inputs->GetInput(VyEnum); _assert_(vy_input);
    4636         Input* vzstokes_input=NULL;
    4637         if(approximation==PattynStokesApproximationEnum || approximation==MacAyealStokesApproximationEnum){
    4638                 vzstokes_input=inputs->GetInput(VzStokesEnum); _assert_(vzstokes_input);
    4639         }
    4640 
    4641         /* Start  looping on the number of gaussian points: */
    4642         gauss=new GaussPenta(2,2);
    4643         for (ig=gauss->begin();ig<gauss->end();ig++){
    4644 
    4645                 gauss->GaussPoint(ig);
    4646 
    4647                 GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss);
    4648                 GetNodalFunctionsP1(basis, gauss);
    4649 
    4650                 vx_input->GetParameterDerivativeValue(&du[0],&xyz_list[0][0],gauss);
    4651                 vy_input->GetParameterDerivativeValue(&dv[0],&xyz_list[0][0],gauss);
    4652                 if(approximation==PattynStokesApproximationEnum || approximation==MacAyealStokesApproximationEnum){
    4653                         vzstokes_input->GetParameterDerivativeValue(&dw[0],&xyz_list[0][0],gauss);
    4654                         dwdz=dw[2];
    4655                 }
    4656                 else dwdz=0;
    4657                 dudx=du[0];
    4658                 dvdy=dv[1];
    4659 
    4660                 for (i=0;i<numdof;i++) pe->values[i] += (dudx+dvdy+dwdz)*Jdet*gauss->weight*basis[i];
    4661         }
    4662 
    4663         /*Clean up and return*/
    4664         delete gauss;
    4665         return pe;
    4666 }
    4667 /*}}}*/
    4668 /*FUNCTION Penta::CreatePVectorDiagnosticVertBase {{{1*/
    4669 ElementVector* Penta::CreatePVectorDiagnosticVertBase(void){
    4670 
    4671 
    4672         /*Constants*/
    4673         const int    numdof=NDOF1*NUMVERTICES;
    4674 
    4675         /*Intermediaries */
    4676         int        i,j,ig;
    4677         int        approximation;
    4678         double     xyz_list[NUMVERTICES][3];
    4679         double     xyz_list_tria[NUMVERTICES2D][3];
    4680         double     Jdet2d;
    4681         double     vx,vy,vz,dbdx,dbdy,basalmeltingvalue;
    4682         double     slope[3];
    4683         double     basis[NUMVERTICES];
    4684         GaussPenta* gauss=NULL;
    4685 
    4686         if (!IsOnBed()) return NULL;
    4687 
    4688         /*Initialize Element vector*/
    4689         ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters);
    4690 
    4691         /*Retrieve all inputs and parameters*/
    4692         GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
    4693         for(i=0;i<NUMVERTICES2D;i++) for(j=0;j<3;j++) xyz_list_tria[i][j]=xyz_list[i][j];
    4694         inputs->GetParameterValue(&approximation,ApproximationEnum);
    4695         Input* bed_input=inputs->GetInput(BedEnum);                                _assert_(bed_input);
    4696         Input* basal_melting_input=inputs->GetInput(BasalforcingsMeltingRateEnum); _assert_(basal_melting_input);
    4697         Input* vx_input=inputs->GetInput(VxEnum);                                  _assert_(vx_input);
    4698         Input* vy_input=inputs->GetInput(VyEnum);                                  _assert_(vy_input);
    4699         Input* vzstokes_input=NULL;
    4700         if(approximation==PattynStokesApproximationEnum || approximation==MacAyealStokesApproximationEnum){
    4701                 vzstokes_input=inputs->GetInput(VzStokesEnum);       _assert_(vzstokes_input);
    4702         }
    4703 
    4704         /* Start  looping on the number of gaussian points: */
    4705         gauss=new GaussPenta(0,1,2,2);
    4706         for(ig=gauss->begin();ig<gauss->end();ig++){
    4707 
    4708                 gauss->GaussPoint(ig);
    4709 
    4710                 basal_melting_input->GetParameterValue(&basalmeltingvalue, gauss);
    4711                 bed_input->GetParameterDerivativeValue(&slope[0],&xyz_list[0][0],gauss);
    4712                 vx_input->GetParameterValue(&vx, gauss);
    4713                 vy_input->GetParameterValue(&vy, gauss);
    4714                 if(approximation==PattynStokesApproximationEnum || approximation==MacAyealStokesApproximationEnum){
    4715                         vzstokes_input->GetParameterValue(&vz, gauss);
    4716                 }
    4717                 else vz=0;
    4718 
    4719                 dbdx=slope[0];
    4720                 dbdy=slope[1];
    4721 
    4722                 GetTriaJacobianDeterminant(&Jdet2d, &xyz_list_tria[0][0],gauss);
    4723                 GetNodalFunctionsP1(&basis[0], gauss);
    4724 
    4725                 for(i=0;i<numdof;i++) pe->values[i]+=-Jdet2d*gauss->weight*(vx*dbdx+vy*dbdy-vz-basalmeltingvalue)*basis[i];
    4726         }
    4727 
    4728         /*Clean up and return*/
    4729         delete gauss;
    4730         return pe;
    4731691}
    4732692/*}}}*/
     
    5029989
    5030990        /*Just branch to the correct InputUpdateFromSolution generator, according to the type of analysis we are carrying out: */
    5031         if (analysis_type==DiagnosticHorizAnalysisEnum){
     991        switch(analysis_type){
     992        #ifdef _HAVE_DIAGNOSTIC_
     993        case DiagnosticHorizAnalysisEnum:
    5032994                int approximation;
    5033995                inputs->GetParameterValue(&approximation,ApproximationEnum);
     
    50411003                        return; //the elements around will create the solution
    50421004                }
    5043         }
    5044         else if(analysis_type==DiagnosticHutterAnalysisEnum){
     1005                break;
     1006        case DiagnosticHutterAnalysisEnum:
    50451007                GetSolutionFromInputsDiagnosticHutter(solution);
    5046         }
    5047         else if(analysis_type==DiagnosticVertAnalysisEnum){
     1008                break;
     1009        case DiagnosticVertAnalysisEnum:
    50481010                GetSolutionFromInputsDiagnosticVert(solution);
    5049         }
     1011                break;
     1012        #endif
    50501013        #ifdef _HAVE_THERMAL_
    5051         else if(analysis_type==ThermalAnalysisEnum){
     1014        case ThermalAnalysisEnum:
    50521015                GetSolutionFromInputsThermal(solution);
    5053         }
    5054         else if(analysis_type==EnthalpyAnalysisEnum){
     1016                break;
     1017        case EnthalpyAnalysisEnum:
    50551018                GetSolutionFromInputsEnthalpy(solution);
    5056         }
     1019                break;
    50571020        #endif
    5058         else{
     1021        default:
    50591022                _error_("analysis: %i (%s) not supported yet",analysis_type,EnumToStringx(analysis_type));
    50601023        }
    5061 }
    5062 /*}}}*/
    5063 /*FUNCTION Penta::GetSolutionFromInputsDiagnosticHoriz{{{1*/
    5064 void  Penta::GetSolutionFromInputsDiagnosticHoriz(Vec solution){
    5065 
    5066         const int    numdof=NDOF2*NUMVERTICES;
    5067 
    5068         int          i;
    5069         int          approximation;
    5070         int*         doflist=NULL;
    5071         double       vx,vy;
    5072         double       values[numdof];
    5073         GaussPenta*  gauss;
    5074 
    5075         /*Get approximation enum and dof list: */
    5076         inputs->GetParameterValue(&approximation,ApproximationEnum);
    5077         Input* vx_input=inputs->GetInput(VxEnum); _assert_(vx_input);
    5078         Input* vy_input=inputs->GetInput(VyEnum); _assert_(vy_input);
    5079 
    5080         /*If the element is a coupling, do nothing: every node is also on an other elements
    5081          * (as coupling is between MacAyeal and Pattyn) so the other element will take care of it*/
    5082         GetDofList(&doflist,approximation,GsetEnum);
    5083 
    5084         /*Ok, we have vx and vy in values, fill in vx and vy arrays: */
    5085         /*P1 element only for now*/
    5086         gauss=new GaussPenta();
    5087         for(i=0;i<NUMVERTICES;i++){
    5088 
    5089                 /*Recover vx and vy*/
    5090                 gauss->GaussVertex(i);
    5091                 vx_input->GetParameterValue(&vx,gauss);
    5092                 vy_input->GetParameterValue(&vy,gauss);
    5093                 values[i*NDOF2+0]=vx;
    5094                 values[i*NDOF2+1]=vy;
    5095         }
    5096 
    5097         /*Add value to global vector*/
    5098         VecSetValues(solution,numdof,doflist,(const double*)values,INSERT_VALUES);
    5099 
    5100         /*Free ressources:*/
    5101         delete gauss;
    5102         xfree((void**)&doflist);
    5103 }
    5104 /*}}}*/
    5105 /*FUNCTION Penta::GetSolutionFromInputsDiagnosticHutter{{{1*/
    5106 void  Penta::GetSolutionFromInputsDiagnosticHutter(Vec solution){
    5107 
    5108         const int    numdof=NDOF2*NUMVERTICES;
    5109 
    5110         int          i;
    5111         int*         doflist=NULL;
    5112         double       vx,vy;
    5113         double       values[numdof];
    5114         GaussPenta*  gauss=NULL;
    5115 
    5116         /*Get dof list: */
    5117         GetDofList(&doflist,NoneApproximationEnum,GsetEnum);
    5118         Input* vx_input=inputs->GetInput(VxEnum); _assert_(vx_input);
    5119         Input* vy_input=inputs->GetInput(VyEnum); _assert_(vy_input);
    5120 
    5121         /*Ok, we have vx and vy in values, fill in vx and vy arrays: */
    5122         /*P1 element only for now*/
    5123         gauss=new GaussPenta();
    5124         for(i=0;i<NUMVERTICES;i++){
    5125                 /*Recover vx and vy*/
    5126                 gauss->GaussVertex(i);
    5127                 vx_input->GetParameterValue(&vx,gauss);
    5128                 vy_input->GetParameterValue(&vy,gauss);
    5129                 values[i*NDOF2+0]=vx;
    5130                 values[i*NDOF2+1]=vy;
    5131         }
    5132 
    5133         /*Add value to global vector*/
    5134         VecSetValues(solution,numdof,doflist,(const double*)values,INSERT_VALUES);
    5135 
    5136         /*Free ressources:*/
    5137         delete gauss;
    5138         xfree((void**)&doflist);
    5139 }
    5140 /*}}}*/
    5141 /*FUNCTION Penta::GetSolutionFromInputsDiagnosticVert{{{1*/
    5142 void  Penta::GetSolutionFromInputsDiagnosticVert(Vec solution){
    5143 
    5144         const int    numdof=NDOF1*NUMVERTICES;
    5145 
    5146         int          i;
    5147         int*         doflist=NULL;
    5148         double       vz;
    5149         double       values[numdof];
    5150         GaussPenta*  gauss=NULL;
    5151 
    5152         /*Get dof list: */
    5153         GetDofList(&doflist,NoneApproximationEnum,GsetEnum);
    5154         Input* vz_input=inputs->GetInput(VzEnum); _assert_(vz_input);
    5155 
    5156         /*Ok, we have vx and vy in values, fill in vx and vy arrays: */
    5157         /*P1 element only for now*/
    5158         gauss=new GaussPenta();
    5159         for(i=0;i<NUMVERTICES;i++){
    5160                 /*Recover vz */
    5161                 gauss->GaussVertex(i);
    5162                 vz_input->GetParameterValue(&vz,gauss);
    5163                 values[i]=vz;
    5164         }
    5165 
    5166         /*Add value to global vector*/
    5167         VecSetValues(solution,numdof,doflist,(const double*)values,INSERT_VALUES);
    5168 
    5169         /*Free ressources:*/
    5170         delete gauss;
    5171         xfree((void**)&doflist);
    5172 }
    5173 /*}}}*/
    5174 /*FUNCTION Penta::GetSolutionFromInputsDiagnosticStokes{{{1*/
    5175 void  Penta::GetSolutionFromInputsDiagnosticStokes(Vec solution){
    5176 
    5177         const int    numdof=NDOF4*NUMVERTICES;
    5178 
    5179         int          i;
    5180         int*         doflist=NULL;
    5181         double       vx,vy,vz,p;
    5182         double       stokesreconditioning;
    5183         double       values[numdof];
    5184         GaussPenta   *gauss;
    5185 
    5186         /*Get dof list: */
    5187         GetDofList(&doflist,StokesApproximationEnum,GsetEnum);
    5188         Input* vx_input=inputs->GetInput(VxEnum);       _assert_(vx_input);
    5189         Input* vy_input=inputs->GetInput(VyEnum);       _assert_(vy_input);
    5190         Input* vz_input=inputs->GetInput(VzEnum);       _assert_(vz_input);
    5191         Input* p_input =inputs->GetInput(PressureEnum); _assert_(p_input);
    5192 
    5193         /*Recondition pressure: */
    5194         this->parameters->FindParam(&stokesreconditioning,DiagnosticStokesreconditioningEnum);
    5195 
    5196         /*Ok, we have vx vy vz and P in values, fill in vx vy vz P arrays: */
    5197         /*P1 element only for now*/
    5198         gauss=new GaussPenta();
    5199         for(i=0;i<NUMVERTICES;i++){
    5200                 gauss->GaussVertex(i);
    5201                 vx_input->GetParameterValue(&vx,gauss);
    5202                 vy_input->GetParameterValue(&vy,gauss);
    5203                 vz_input->GetParameterValue(&vz,gauss);
    5204                 p_input ->GetParameterValue(&p ,gauss);
    5205                 values[i*NDOF4+0]=vx;
    5206                 values[i*NDOF4+1]=vy;
    5207                 values[i*NDOF4+2]=vz;
    5208                 values[i*NDOF4+3]=p/stokesreconditioning;
    5209         }
    5210 
    5211         /*Add value to global vector*/
    5212         VecSetValues(solution,numdof,doflist,(const double*)values,INSERT_VALUES);
    5213 
    5214         /*Free ressources:*/
    5215         delete gauss;
    5216         xfree((void**)&doflist);
    52171024}
    52181025/*}}}*/
     
    58511658
    58521659        /*Just branch to the correct InputUpdateFromSolution generator, according to the type of analysis we are carrying out: */
    5853         if (analysis_type==DiagnosticHorizAnalysisEnum){
     1660        switch(analysis_type){
     1661        #ifdef _HAVE_DIAGNOSTIC_
     1662        case DiagnosticHorizAnalysisEnum:
    58541663                InputUpdateFromSolutionDiagnosticHoriz( solution);
    5855         }
    5856         else if (analysis_type==DiagnosticHutterAnalysisEnum){
     1664                break;
     1665        case DiagnosticHutterAnalysisEnum:
    58571666                InputUpdateFromSolutionDiagnosticHutter( solution);
    5858         }
    5859         else if (analysis_type==DiagnosticVertAnalysisEnum){
     1667                break;
     1668        case DiagnosticVertAnalysisEnum:
    58601669                InputUpdateFromSolutionDiagnosticVert( solution);
    5861         }
     1670                break;
     1671        #endif
    58621672        #ifdef _HAVE_CONTROL_
    5863         else if (analysis_type==AdjointHorizAnalysisEnum){
     1673        case AdjointHorizAnalysisEnum:
    58641674                int approximation;
    58651675                inputs->GetParameterValue(&approximation,ApproximationEnum);
     
    58701680                        InputUpdateFromSolutionAdjointHoriz( solution);
    58711681                }
    5872         }
     1682                break;
    58731683        #endif
    5874         else if (analysis_type==BedSlopeXAnalysisEnum){
     1684        #ifdef _HAVE_THERMAL_
     1685        case ThermalAnalysisEnum:
     1686                InputUpdateFromSolutionThermal( solution);
     1687                break;
     1688        case EnthalpyAnalysisEnum:
     1689                InputUpdateFromSolutionEnthalpy( solution);
     1690                break;
     1691        case MeltingAnalysisEnum:
     1692                InputUpdateFromSolutionOneDof(solution,BasalforcingsMeltingRateEnum);
     1693                break;
     1694        #endif
     1695        case BedSlopeXAnalysisEnum:
    58751696                InputUpdateFromSolutionOneDofCollapsed(solution,BedSlopeXEnum);
    5876         }
    5877         else if (analysis_type==BedSlopeYAnalysisEnum){
     1697                break;
     1698        case BedSlopeYAnalysisEnum:
    58781699                InputUpdateFromSolutionOneDofCollapsed(solution,BedSlopeYEnum);
    5879         }
    5880         else if (analysis_type==SurfaceSlopeXAnalysisEnum){
     1700                break;
     1701        case SurfaceSlopeXAnalysisEnum:
    58811702                InputUpdateFromSolutionOneDofCollapsed(solution,SurfaceSlopeXEnum);
    5882         }
    5883         else if (analysis_type==SurfaceSlopeYAnalysisEnum){
     1703                break;
     1704        case SurfaceSlopeYAnalysisEnum:
    58841705                InputUpdateFromSolutionOneDofCollapsed(solution,SurfaceSlopeYEnum);
    5885         }
    5886         else if (analysis_type==PrognosticAnalysisEnum){
     1706                break;
     1707        case PrognosticAnalysisEnum:
    58871708                InputUpdateFromSolutionPrognostic(solution);
    5888         }
    5889         else if (analysis_type==BalancethicknessAnalysisEnum){
     1709                break;
     1710        #ifdef _HAVE_BALANCED_
     1711        case BalancethicknessAnalysisEnum:
    58901712                InputUpdateFromSolutionOneDofCollapsed(solution,ThicknessEnum);
    5891         }
    5892         #ifdef _HAVE_THERMAL_
    5893         else if (analysis_type==ThermalAnalysisEnum){
    5894                 InputUpdateFromSolutionThermal( solution);
    5895         }
    5896         else if (analysis_type==EnthalpyAnalysisEnum){
    5897                 InputUpdateFromSolutionEnthalpy( solution);
    5898         }
    5899         else if (analysis_type==MeltingAnalysisEnum){
    5900                 InputUpdateFromSolutionOneDof(solution,BasalforcingsMeltingRateEnum);
    5901         }
     1713                break;
    59021714        #endif
    5903         else{
     1715        default:
    59041716                _error_("analysis %i (%s) not supported yet",analysis_type,EnumToStringx(analysis_type));
    59051717        }
    5906 }
    5907 /*}}}*/
    5908 /*FUNCTION Penta::InputUpdateFromSolutionDiagnosticHoriz {{{1*/
    5909 void  Penta::InputUpdateFromSolutionDiagnosticHoriz(double* solution){
    5910 
    5911         int  approximation;
    5912 
    5913         /*Recover inputs*/
    5914         inputs->GetParameterValue(&approximation,ApproximationEnum);
    5915 
    5916         /*MacAyeal, everything is done by the element on bed*/
    5917         if (approximation==MacAyealApproximationEnum){
    5918                 if (!IsOnBed()){
    5919                         /*Do nothing. Element on bed will take care of it*/
    5920                         return;
    5921                 }
    5922                 else{
    5923                         InputUpdateFromSolutionDiagnosticMacAyeal(solution);
    5924                         return;
    5925                 }
    5926         }
    5927         else if (approximation==PattynApproximationEnum){
    5928                 InputUpdateFromSolutionDiagnosticPattyn(solution);
    5929         }
    5930         else if (approximation==PattynStokesApproximationEnum){
    5931                 InputUpdateFromSolutionDiagnosticPattynStokes(solution);
    5932         }
    5933         else if (approximation==MacAyealStokesApproximationEnum){
    5934                 InputUpdateFromSolutionDiagnosticMacAyealStokes(solution);
    5935         }
    5936         else if (approximation==StokesApproximationEnum || approximation==NoneApproximationEnum){
    5937                 InputUpdateFromSolutionDiagnosticStokes(solution);
    5938         }
    5939         else if (approximation==MacAyealPattynApproximationEnum){
    5940                 InputUpdateFromSolutionDiagnosticMacAyealPattyn(solution);
    5941         }
    5942 }
    5943 /*}}}*/
    5944 /*FUNCTION Penta::InputUpdateFromSolutionDiagnosticMacAyeal {{{1*/
    5945 void  Penta::InputUpdateFromSolutionDiagnosticMacAyeal(double* solution){
    5946 
    5947         const int    numdof=NDOF2*NUMVERTICES;
    5948 
    5949         int     i,dummy;
    5950         double  rho_ice,g;
    5951         double  values[numdof];
    5952         double  vx[NUMVERTICES];
    5953         double  vy[NUMVERTICES];
    5954         double  vz[NUMVERTICES];
    5955         double  vel[NUMVERTICES];
    5956         double  pressure[NUMVERTICES];
    5957         double  surface[NUMVERTICES];
    5958         double  xyz_list[NUMVERTICES][3];
    5959         int    *doflist = NULL;
    5960         double *vz_ptr  = NULL;
    5961         Penta  *penta   = NULL;
    5962 
    5963         /*Get dof list: */
    5964         GetDofList(&doflist,MacAyealApproximationEnum,GsetEnum);
    5965 
    5966         /*Use the dof list to index into the solution vector: */
    5967         for(i=0;i<numdof;i++) values[i]=solution[doflist[i]];
    5968 
    5969         /*Ok, we have vx and vy in values, fill in vx and vy arrays and extrude */
    5970         for(i=0;i<3;i++){
    5971                 vx[i]  =values[i*NDOF2+0];
    5972                 vy[i]  =values[i*NDOF2+1];
    5973                 vx[i+3]=vx[i];
    5974                 vy[i+3]=vy[i];
    5975 
    5976                 /*Check solution*/
    5977                 if(isnan(vx[i])) _error_("NaN found in solution vector");
    5978                 if(isnan(vy[i])) _error_("NaN found in solution vector");
    5979         }
    5980 
    5981         /*Get parameters fro pressure computation*/
    5982         rho_ice=matpar->GetRhoIce();
    5983         g=matpar->GetG();
    5984 
    5985         /*Start looping over all elements above current element and update all inputs*/
    5986         penta=this;
    5987         for(;;){
    5988 
    5989                 /*Get node data: */
    5990                 GetVerticesCoordinates(&xyz_list[0][0],penta->nodes,NUMVERTICES);
    5991 
    5992                 /*Now Compute vel*/
    5993                 Input* vz_input=inputs->GetInput(VzEnum);
    5994                 if (vz_input){
    5995                         if (vz_input->Enum()!=PentaVertexInputEnum) _error_("Cannot compute Vel as Vz is of type %s",EnumToStringx(vz_input->Enum()));
    5996                         vz_input->GetValuesPtr(&vz_ptr,&dummy);
    5997                         for(i=0;i<NUMVERTICES;i++) vz[i]=vz_ptr[i];
    5998                 }
    5999                 else{for(i=0;i<NUMVERTICES;i++) vz[i]=0.0;}
    6000                 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);
    6001 
    6002                 /*Now compute pressure*/
    6003                 GetParameterListOnVertices(&surface[0],SurfaceEnum);
    6004                 for(i=0;i<NUMVERTICES;i++) pressure[i]=rho_ice*g*(surface[i]-xyz_list[i][2]);
    6005 
    6006                 /*Now, we have to move the previous Vx and Vy inputs  to old
    6007                  * status, otherwise, we'll wipe them off: */
    6008                 penta->inputs->ChangeEnum(VxEnum,VxPicardEnum);
    6009                 penta->inputs->ChangeEnum(VyEnum,VyPicardEnum);
    6010                 penta->inputs->ChangeEnum(PressureEnum,PressurePicardEnum);
    6011 
    6012                 /*Add vx and vy as inputs to the tria element: */
    6013                 penta->inputs->AddInput(new PentaVertexInput(VxEnum,vx));
    6014                 penta->inputs->AddInput(new PentaVertexInput(VyEnum,vy));
    6015                 penta->inputs->AddInput(new PentaVertexInput(VelEnum,vel));
    6016                 penta->inputs->AddInput(new PentaVertexInput(PressureEnum,pressure));
    6017 
    6018                 /*Stop if we have reached the surface*/
    6019                 if (penta->IsOnSurface()) break;
    6020 
    6021                 /* get upper Penta*/
    6022                 penta=penta->GetUpperElement(); _assert_(penta->Id()!=this->id);
    6023         }
    6024        
    6025         /*Free ressources:*/
    6026         xfree((void**)&doflist);
    6027 }
    6028 /*}}}*/
    6029 /*FUNCTION Penta::InputUpdateFromSolutionDiagnosticMacAyealPattyn {{{1*/
    6030 void  Penta::InputUpdateFromSolutionDiagnosticMacAyealPattyn(double* solution){
    6031 
    6032         const int    numdof=NDOF2*NUMVERTICES;
    6033         const int    numdof2d=NDOF2*NUMVERTICES2D;
    6034 
    6035         int     i,dummy;
    6036         double  rho_ice,g;
    6037         double  macayeal_values[numdof];
    6038         double  pattyn_values[numdof];
    6039         double  vx[NUMVERTICES];
    6040         double  vy[NUMVERTICES];
    6041         double  vz[NUMVERTICES];
    6042         double  vel[NUMVERTICES];
    6043         double  pressure[NUMVERTICES];
    6044         double  surface[NUMVERTICES];
    6045         double  xyz_list[NUMVERTICES][3];
    6046         int*    doflistp = NULL;
    6047         int*    doflistm = NULL;
    6048         double  *vz_ptr  = NULL;
    6049         Penta   *penta   = NULL;
    6050 
    6051         /*OK, we have to add results of this element for pattyn
    6052          * and results from the penta at base for macayeal. Now recover results*/
    6053         penta=GetBasalElement();
    6054 
    6055         /*Get dof listof this element (pattyn dofs) and of the penta at base (macayeal dofs): */
    6056         GetDofList(&doflistp,PattynApproximationEnum,GsetEnum);
    6057         penta->GetDofList(&doflistm,MacAyealApproximationEnum,GsetEnum);
    6058 
    6059         /*Get node data: */
    6060         GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
    6061 
    6062         /*Use the dof list to index into the solution vector: */
    6063         for(i=0;i<numdof2d;i++){
    6064                 pattyn_values[i]=solution[doflistp[i]];
    6065                 macayeal_values[i]=solution[doflistm[i]];
    6066         }
    6067         for(i=numdof2d;i<numdof;i++){
    6068                 pattyn_values[i]=solution[doflistp[i]];
    6069                 macayeal_values[i]=macayeal_values[i-numdof2d];
    6070         }
    6071 
    6072         /*Ok, we have vx and vy in values, fill in vx and vy arrays: */
    6073         for(i=0;i<NUMVERTICES;i++){
    6074                 vx[i]=macayeal_values[i*NDOF2+0]+pattyn_values[i*NDOF2+0];
    6075                 vy[i]=macayeal_values[i*NDOF2+1]+pattyn_values[i*NDOF2+1];
    6076 
    6077                 /*Check solution*/
    6078                 if(isnan(vx[i])) _error_("NaN found in solution vector");
    6079                 if(isnan(vy[i])) _error_("NaN found in solution vector");
    6080         }
    6081 
    6082         /*Get Vz*/
    6083         Input* vz_input=inputs->GetInput(VzEnum);
    6084         if (vz_input){
    6085                 if (vz_input->Enum()!=PentaVertexInputEnum){
    6086                         _error_("Cannot compute Vel as Vz is of type %s",EnumToStringx(vz_input->Enum()));
    6087                 }
    6088                 vz_input->GetValuesPtr(&vz_ptr,&dummy);
    6089                 for(i=0;i<NUMVERTICES;i++) vz[i]=vz_ptr[i];
    6090         }
    6091         else{
    6092                 for(i=0;i<NUMVERTICES;i++) vz[i]=0.0;
    6093         }
    6094 
    6095         /*Now Compute vel*/
    6096         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);
    6097 
    6098         /*For pressure: we have not computed pressure in this analysis, for this element. We are in 3D,
    6099          *so the pressure is just the pressure at the z elevation: */
    6100         rho_ice=matpar->GetRhoIce();
    6101         g=matpar->GetG();
    6102         GetParameterListOnVertices(&surface[0],SurfaceEnum);
    6103         for(i=0;i<NUMVERTICES;i++) pressure[i]=rho_ice*g*(surface[i]-xyz_list[i][2]);
    6104 
    6105         /*Now, we have to move the previous Vx and Vy inputs  to old
    6106          * status, otherwise, we'll wipe them off: */
    6107         this->inputs->ChangeEnum(VxEnum,VxPicardEnum);
    6108         this->inputs->ChangeEnum(VyEnum,VyPicardEnum);
    6109         this->inputs->ChangeEnum(PressureEnum,PressurePicardEnum);
    6110 
    6111         /*Add vx and vy as inputs to the tria element: */
    6112         this->inputs->AddInput(new PentaVertexInput(VxEnum,vx));
    6113         this->inputs->AddInput(new PentaVertexInput(VyEnum,vy));
    6114         this->inputs->AddInput(new PentaVertexInput(VelEnum,vel));
    6115         this->inputs->AddInput(new PentaVertexInput(PressureEnum,pressure));
    6116 
    6117         /*Free ressources:*/
    6118         xfree((void**)&doflistp);
    6119         xfree((void**)&doflistm);
    6120 }
    6121 /*}}}*/
    6122 /*FUNCTION Penta::InputUpdateFromSolutionDiagnosticMacAyealStokes {{{1*/
    6123 void  Penta::InputUpdateFromSolutionDiagnosticMacAyealStokes(double* solution){
    6124 
    6125         const int    numdofm=NDOF2*NUMVERTICES;
    6126         const int    numdofs=NDOF4*NUMVERTICES;
    6127         const int    numdof2d=NDOF2*NUMVERTICES2D;
    6128 
    6129         int     i,dummy;
    6130         double  stokesreconditioning;
    6131         double  macayeal_values[numdofm];
    6132         double  stokes_values[numdofs];
    6133         double  vx[NUMVERTICES];
    6134         double  vy[NUMVERTICES];
    6135         double  vz[NUMVERTICES];
    6136         double  vzmacayeal[NUMVERTICES];
    6137         double  vzstokes[NUMVERTICES];
    6138         double  vel[NUMVERTICES];
    6139         double  pressure[NUMVERTICES];
    6140         double  xyz_list[NUMVERTICES][3];
    6141         int*    doflistm        = NULL;
    6142         int*    doflists        = NULL;
    6143         double  *vzmacayeal_ptr = NULL;
    6144         Penta   *penta          = NULL;
    6145 
    6146         /*OK, we have to add results of this element for macayeal
    6147          * and results from the penta at base for macayeal. Now recover results*/
    6148         penta=GetBasalElement();
    6149 
    6150         /*Get dof listof this element (macayeal dofs) and of the penta at base (macayeal dofs): */
    6151         penta->GetDofList(&doflistm,MacAyealApproximationEnum,GsetEnum);
    6152         GetDofList(&doflists,StokesApproximationEnum,GsetEnum);
    6153         this->parameters->FindParam(&stokesreconditioning,DiagnosticStokesreconditioningEnum);
    6154 
    6155         /*Get node data: */
    6156         GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
    6157 
    6158         /*Use the dof list to index into the solution vector: */
    6159         for(i=0;i<numdof2d;i++){
    6160                 macayeal_values[i]=solution[doflistm[i]];
    6161                 macayeal_values[i+numdof2d]=solution[doflistm[i]];
    6162         }
    6163         for(i=0;i<numdofs;i++){
    6164                 stokes_values[i]=solution[doflists[i]];
    6165         }
    6166 
    6167         /*Ok, we have vx and vy in values, fill in vx and vy arrays: */
    6168         for(i=0;i<NUMVERTICES;i++){
    6169                 vx[i]=stokes_values[i*NDOF4+0]+macayeal_values[i*NDOF2+0];
    6170                 vy[i]=stokes_values[i*NDOF4+1]+macayeal_values[i*NDOF2+1];
    6171                 vzstokes[i]=stokes_values[i*NDOF4+2];
    6172                 pressure[i]=stokes_values[i*NDOF4+3]*stokesreconditioning;
    6173 
    6174                 /*Check solution*/
    6175                 if(isnan(vx[i]))       _error_("NaN found in solution vector");
    6176                 if(isnan(vy[i]))       _error_("NaN found in solution vector");
    6177                 if(isnan(vzstokes[i])) _error_("NaN found in solution vector");
    6178                 if(isnan(pressure[i])) _error_("NaN found in solution vector");
    6179         }
    6180 
    6181         /*Get Vz*/
    6182         Input* vzmacayeal_input=inputs->GetInput(VzMacAyealEnum);
    6183         if (vzmacayeal_input){
    6184                 if (vzmacayeal_input->Enum()!=PentaVertexInputEnum){
    6185                         _error_("Cannot compute Vel as VzMacAyeal is of type %s",EnumToStringx(vzmacayeal_input->Enum()));
    6186                 }
    6187                 vzmacayeal_input->GetValuesPtr(&vzmacayeal_ptr,&dummy);
    6188                 for(i=0;i<NUMVERTICES;i++) vzmacayeal[i]=vzmacayeal_ptr[i];
    6189         }
    6190         else{
    6191                 _error_("Cannot update solution as VzMacAyeal is not present");
    6192         }
    6193 
    6194         /*Now Compute vel*/
    6195         for(i=0;i<NUMVERTICES;i++) {
    6196                 vz[i]=vzmacayeal[i]+vzstokes[i];
    6197                 vel[i]=pow( pow(vx[i],2.0) + pow(vy[i],2.0) + pow(vz[i],2.0) , 0.5);
    6198         }
    6199 
    6200         /*Now, we have to move the previous Vx and Vy inputs  to old
    6201          * status, otherwise, we'll wipe them off: */
    6202         this->inputs->ChangeEnum(VxEnum,VxPicardEnum);
    6203         this->inputs->ChangeEnum(VyEnum,VyPicardEnum);
    6204         this->inputs->ChangeEnum(VzEnum,VzPicardEnum);
    6205         this->inputs->ChangeEnum(PressureEnum,PressurePicardEnum);
    6206 
    6207         /*Add vx and vy as inputs to the tria element: */
    6208         this->inputs->AddInput(new PentaVertexInput(VxEnum,vx));
    6209         this->inputs->AddInput(new PentaVertexInput(VyEnum,vy));
    6210         this->inputs->AddInput(new PentaVertexInput(VzEnum,vz));
    6211         this->inputs->AddInput(new PentaVertexInput(VzStokesEnum,vzstokes));
    6212         this->inputs->AddInput(new PentaVertexInput(VelEnum,vel));
    6213         this->inputs->AddInput(new PentaVertexInput(PressureEnum,pressure));
    6214 
    6215         /*Free ressources:*/
    6216         xfree((void**)&doflistm);
    6217         xfree((void**)&doflists);
    6218 }
    6219 /*}}}*/
    6220 /*FUNCTION Penta::InputUpdateFromSolutionDiagnosticPattyn {{{1*/
    6221 void  Penta::InputUpdateFromSolutionDiagnosticPattyn(double* solution){
    6222        
    6223         const int    numdof=NDOF2*NUMVERTICES;
    6224 
    6225         int    i,dummy;
    6226         double rho_ice,g;
    6227         double values[numdof];
    6228         double vx[NUMVERTICES];
    6229         double vy[NUMVERTICES];
    6230         double vz[NUMVERTICES];
    6231         double vel[NUMVERTICES];
    6232         double pressure[NUMVERTICES];
    6233         double surface[NUMVERTICES];
    6234         double xyz_list[NUMVERTICES][3];
    6235         int*   doflist = NULL;
    6236 
    6237         /*Get dof list: */
    6238         GetDofList(&doflist,PattynApproximationEnum,GsetEnum);
    6239 
    6240         /*Get node data: */
    6241         GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
    6242 
    6243         /*Use the dof list to index into the solution vector: */
    6244         for(i=0;i<numdof;i++) values[i]=solution[doflist[i]];
    6245 
    6246         /*Ok, we have vx and vy in values, fill in vx and vy arrays: */
    6247         for(i=0;i<NUMVERTICES;i++){
    6248                 vx[i]=values[i*NDOF2+0];
    6249                 vy[i]=values[i*NDOF2+1];
    6250 
    6251                 /*Check solution*/
    6252                 if(isnan(vx[i])) _error_("NaN found in solution vector");
    6253                 if(isnan(vy[i])) _error_("NaN found in solution vector");
    6254         }
    6255 
    6256         /*Get Vz*/
    6257         Input* vz_input=inputs->GetInput(VzEnum);
    6258         if (vz_input){
    6259                 GetParameterListOnVertices(&vz[0],VzEnum);
    6260         }
    6261         else{
    6262                 for(i=0;i<NUMVERTICES;i++) vz[i]=0.0;
    6263         }
    6264 
    6265         /*Now Compute vel*/
    6266         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);
    6267 
    6268         /*For pressure: we have not computed pressure in this analysis, for this element. We are in 3D,
    6269          *so the pressure is just the pressure at the z elevation: */
    6270         rho_ice=matpar->GetRhoIce();
    6271         g=matpar->GetG();
    6272         GetParameterListOnVertices(&surface[0],SurfaceEnum);
    6273         for(i=0;i<NUMVERTICES;i++) pressure[i]=rho_ice*g*(surface[i]-xyz_list[i][2]);
    6274 
    6275         /*Now, we have to move the previous Vx and Vy inputs  to old
    6276          * status, otherwise, we'll wipe them off: */
    6277         this->inputs->ChangeEnum(VxEnum,VxPicardEnum);
    6278         this->inputs->ChangeEnum(VyEnum,VyPicardEnum);
    6279         this->inputs->ChangeEnum(PressureEnum,PressurePicardEnum);
    6280 
    6281         /*Add vx and vy as inputs to the tria element: */
    6282         this->inputs->AddInput(new PentaVertexInput(VxEnum,vx));
    6283         this->inputs->AddInput(new PentaVertexInput(VyEnum,vy));
    6284         this->inputs->AddInput(new PentaVertexInput(VelEnum,vel));
    6285         this->inputs->AddInput(new PentaVertexInput(PressureEnum,pressure));
    6286 
    6287         /*Free ressources:*/
    6288         xfree((void**)&doflist);
    6289 }
    6290 /*}}}*/
    6291 /*FUNCTION Penta::InputUpdateFromSolutionDiagnosticPattynStokes {{{1*/
    6292 void  Penta::InputUpdateFromSolutionDiagnosticPattynStokes(double* solution){
    6293 
    6294         const int    numdofp=NDOF2*NUMVERTICES;
    6295         const int    numdofs=NDOF4*NUMVERTICES;
    6296 
    6297         int    i,dummy;
    6298         double pattyn_values[numdofp];
    6299         double stokes_values[numdofs];
    6300         double vx[NUMVERTICES];
    6301         double vy[NUMVERTICES];
    6302         double vz[NUMVERTICES];
    6303         double vzpattyn[NUMVERTICES];
    6304         double vzstokes[NUMVERTICES];
    6305         double vel[NUMVERTICES];
    6306         double pressure[NUMVERTICES];
    6307         double xyz_list[NUMVERTICES][3];
    6308         double stokesreconditioning;
    6309         int*   doflistp      = NULL;
    6310         int*   doflists      = NULL;
    6311         double *vzpattyn_ptr = NULL;
    6312         Penta  *penta        = NULL;
    6313 
    6314         /*OK, we have to add results of this element for pattyn
    6315          * and results from the penta at base for macayeal. Now recover results*/
    6316         penta=GetBasalElement();
    6317 
    6318         /*Get dof listof this element (pattyn dofs) and of the penta at base (macayeal dofs): */
    6319         GetDofList(&doflistp,PattynApproximationEnum,GsetEnum);
    6320         GetDofList(&doflists,StokesApproximationEnum,GsetEnum);
    6321         this->parameters->FindParam(&stokesreconditioning,DiagnosticStokesreconditioningEnum);
    6322 
    6323         /*Get node data: */
    6324         GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
    6325 
    6326         /*Use the dof list to index into the solution vector: */
    6327         for(i=0;i<numdofp;i++) pattyn_values[i]=solution[doflistp[i]];
    6328         for(i=0;i<numdofs;i++) stokes_values[i]=solution[doflists[i]];
    6329 
    6330         /*Ok, we have vx and vy in values, fill in vx and vy arrays: */
    6331         for(i=0;i<NUMVERTICES;i++){
    6332                 vx[i]=stokes_values[i*NDOF4+0]+pattyn_values[i*NDOF2+0];
    6333                 vy[i]=stokes_values[i*NDOF4+1]+pattyn_values[i*NDOF2+1];
    6334                 vzstokes[i]=stokes_values[i*NDOF4+2];
    6335                 pressure[i]=stokes_values[i*NDOF4+3]*stokesreconditioning;
    6336 
    6337                 /*Check solution*/
    6338                 if(isnan(vx[i]))       _error_("NaN found in solution vector");
    6339                 if(isnan(vy[i]))       _error_("NaN found in solution vector");
    6340                 if(isnan(vzstokes[i])) _error_("NaN found in solution vector");
    6341                 if(isnan(pressure[i])) _error_("NaN found in solution vector");
    6342         }
    6343 
    6344         /*Get Vz*/
    6345         Input* vzpattyn_input=inputs->GetInput(VzPattynEnum);
    6346         if (vzpattyn_input){
    6347                 if (vzpattyn_input->Enum()!=PentaVertexInputEnum){
    6348                         _error_("Cannot compute Vel as VzPattyn is of type %s",EnumToStringx(vzpattyn_input->Enum()));
    6349                 }
    6350                 vzpattyn_input->GetValuesPtr(&vzpattyn_ptr,&dummy);
    6351                 for(i=0;i<NUMVERTICES;i++) vzpattyn[i]=vzpattyn_ptr[i];
    6352         }
    6353         else{
    6354                 _error_("Cannot update solution as VzPattyn is not present");
    6355         }
    6356 
    6357         /*Now Compute vel*/
    6358         for(i=0;i<NUMVERTICES;i++) {
    6359                 vz[i]=vzpattyn[i]+vzstokes[i];
    6360                 vel[i]=pow( pow(vx[i],2.0) + pow(vy[i],2.0) + pow(vz[i],2.0) , 0.5);
    6361         }
    6362 
    6363         /*Now, we have to move the previous Vx and Vy inputs  to old
    6364          * status, otherwise, we'll wipe them off: */
    6365         this->inputs->ChangeEnum(VxEnum,VxPicardEnum);
    6366         this->inputs->ChangeEnum(VyEnum,VyPicardEnum);
    6367         this->inputs->ChangeEnum(VzEnum,VzPicardEnum);
    6368         this->inputs->ChangeEnum(PressureEnum,PressurePicardEnum);
    6369 
    6370         /*Add vx and vy as inputs to the tria element: */
    6371         this->inputs->AddInput(new PentaVertexInput(VxEnum,vx));
    6372         this->inputs->AddInput(new PentaVertexInput(VyEnum,vy));
    6373         this->inputs->AddInput(new PentaVertexInput(VzEnum,vz));
    6374         this->inputs->AddInput(new PentaVertexInput(VzStokesEnum,vzstokes));
    6375         this->inputs->AddInput(new PentaVertexInput(VelEnum,vel));
    6376         this->inputs->AddInput(new PentaVertexInput(PressureEnum,pressure));
    6377 
    6378         /*Free ressources:*/
    6379         xfree((void**)&doflistp);
    6380         xfree((void**)&doflists);
    6381 }
    6382 /*}}}*/
    6383 /*FUNCTION Penta::InputUpdateFromSolutionDiagnosticHutter {{{1*/
    6384 void  Penta::InputUpdateFromSolutionDiagnosticHutter(double* solution){
    6385        
    6386         const int    numdof=NDOF2*NUMVERTICES;
    6387 
    6388         int     i,dummy;
    6389         double  rho_ice,g;
    6390         double  values[numdof];
    6391         double  vx[NUMVERTICES];
    6392         double  vy[NUMVERTICES];
    6393         double  vz[NUMVERTICES];
    6394         double  vel[NUMVERTICES];
    6395         double  pressure[NUMVERTICES];
    6396         double  surface[NUMVERTICES];
    6397         double  xyz_list[NUMVERTICES][3];
    6398         int*    doflist = NULL;
    6399         double* vz_ptr  = NULL;
    6400 
    6401         /*Get dof list: */
    6402         GetDofList(&doflist,NoneApproximationEnum,GsetEnum);
    6403 
    6404         /*Get node data: */
    6405         GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
    6406 
    6407         /*Use the dof list to index into the solution vector: */
    6408         for(i=0;i<numdof;i++) values[i]=solution[doflist[i]];
    6409 
    6410         /*Ok, we have vx and vy in values, fill in vx and vy arrays: */
    6411         for(i=0;i<NUMVERTICES;i++){
    6412                 vx[i]=values[i*NDOF2+0];
    6413                 vy[i]=values[i*NDOF2+1];
    6414 
    6415                 /*Check solution*/
    6416                 if(isnan(vx[i])) _error_("NaN found in solution vector");
    6417                 if(isnan(vy[i])) _error_("NaN found in solution vector");
    6418         }
    6419 
    6420         /*Get Vz*/
    6421         Input* vz_input=inputs->GetInput(VzEnum);
    6422         if (vz_input){
    6423                 if (vz_input->Enum()!=PentaVertexInputEnum){
    6424                         _error_("Cannot compute Vel as Vz is of type %s",EnumToStringx(vz_input->Enum()));
    6425                 }
    6426                 vz_input->GetValuesPtr(&vz_ptr,&dummy);
    6427                 for(i=0;i<NUMVERTICES;i++) vz[i]=vz_ptr[i];
    6428         }
    6429         else{
    6430                 for(i=0;i<NUMVERTICES;i++) vz[i]=0.0;
    6431         }
    6432 
    6433         /*Now Compute vel*/
    6434         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);
    6435 
    6436         /*For pressure: we have not computed pressure in this analysis, for this element. We are in 3D,
    6437          *so the pressure is just the pressure at the z elevation: */
    6438         rho_ice=matpar->GetRhoIce();
    6439         g=matpar->GetG();
    6440         GetParameterListOnVertices(&surface[0],SurfaceEnum);
    6441         for(i=0;i<NUMVERTICES;i++) pressure[i]=rho_ice*g*(surface[i]-xyz_list[i][2]);
    6442 
    6443         /*Now, we have to move the previous Vx and Vy inputs  to old
    6444          * status, otherwise, we'll wipe them off: */
    6445         this->inputs->ChangeEnum(VxEnum,VxPicardEnum);
    6446         this->inputs->ChangeEnum(VyEnum,VyPicardEnum);
    6447         this->inputs->ChangeEnum(PressureEnum,PressurePicardEnum);
    6448 
    6449         /*Add vx and vy as inputs to the tria element: */
    6450         this->inputs->AddInput(new PentaVertexInput(VxEnum,vx));
    6451         this->inputs->AddInput(new PentaVertexInput(VyEnum,vy));
    6452         this->inputs->AddInput(new TriaVertexInput(VelEnum,vel));
    6453         this->inputs->AddInput(new PentaVertexInput(PressureEnum,pressure));
    6454 
    6455         /*Free ressources:*/
    6456         xfree((void**)&doflist);
    6457 }
    6458 /*}}}*/
    6459 /*FUNCTION Penta::InputUpdateFromSolutionDiagnosticVert {{{1*/
    6460 void  Penta::InputUpdateFromSolutionDiagnosticVert(double* solution){
    6461 
    6462         const int numdof=NDOF1*NUMVERTICES;
    6463        
    6464         int      i,dummy;
    6465         int      approximation;
    6466         double   rho_ice,g;
    6467         double   values[numdof];
    6468         double   vx[NUMVERTICES];
    6469         double   vy[NUMVERTICES];
    6470         double   vz[NUMVERTICES];
    6471         double   vzmacayeal[NUMVERTICES];
    6472         double   vzpattyn[NUMVERTICES];
    6473         double   vzstokes[NUMVERTICES];
    6474         double   vel[NUMVERTICES];
    6475         double   pressure[NUMVERTICES];
    6476         double   surface[NUMVERTICES];
    6477         double   xyz_list[NUMVERTICES][3];
    6478         int*     doflist      = NULL;
    6479         double*  vx_ptr       = NULL;
    6480         double*  vy_ptr       = NULL;
    6481         double*  vzstokes_ptr = NULL;
    6482 
    6483 
    6484         /*Get the approximation and do nothing if the element in Stokes or None*/
    6485         inputs->GetParameterValue(&approximation,ApproximationEnum);
    6486         if(approximation==StokesApproximationEnum || approximation==NoneApproximationEnum){
    6487                 return;
    6488         }
    6489 
    6490         /*Get dof list and vertices coordinates: */
    6491         GetDofList(&doflist,NoneApproximationEnum,GsetEnum);
    6492         GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
    6493 
    6494         /*Use the dof list to index into the solution vector vz: */
    6495         for(i=0;i<numdof;i++) values[i]=solution[doflist[i]];
    6496         for(i=0;i<NUMVERTICES;i++){
    6497                 vz[i]=values[i*NDOF1+0];
    6498 
    6499                 /*Check solution*/
    6500                 if(isnan(vz[i])) _error_("NaN found in solution vector");
    6501         }
    6502 
    6503         /*Get Vx and Vy*/
    6504         Input* vx_input=inputs->GetInput(VxEnum);
    6505         if (vx_input){
    6506                 if (vx_input->Enum()!=PentaVertexInputEnum) _error_("Cannot compute Vel as Vx is of type %s",EnumToStringx(vx_input->Enum()));
    6507                 vx_input->GetValuesPtr(&vx_ptr,&dummy);
    6508                 for(i=0;i<NUMVERTICES;i++) vx[i]=vx_ptr[i];
    6509         }
    6510         else for(i=0;i<NUMVERTICES;i++) vx[i]=0.0;
    6511 
    6512         Input* vy_input=inputs->GetInput(VyEnum);
    6513         if (vy_input){
    6514                 if (vy_input->Enum()!=PentaVertexInputEnum) _error_("Cannot compute Vel as Vy is of type %s",EnumToStringx(vy_input->Enum()));
    6515                 vy_input->GetValuesPtr(&vy_ptr,&dummy);
    6516                 for(i=0;i<NUMVERTICES;i++) vy[i]=vy_ptr[i];
    6517         }
    6518         else for(i=0;i<NUMVERTICES;i++) vy[i]=0.0;
    6519 
    6520         /*Do some modifications if we actually have a PattynStokes or MacAyealStokes element*/
    6521         if(approximation==PattynStokesApproximationEnum){
    6522                 Input* vzstokes_input=inputs->GetInput(VzStokesEnum);
    6523                 if (vzstokes_input){
    6524                         if (vzstokes_input->Enum()!=PentaVertexInputEnum) _error_("Cannot compute Vel as VzStokes is of type %s",EnumToStringx(vy_input->Enum()));
    6525                         vzstokes_input->GetValuesPtr(&vzstokes_ptr,&dummy);
    6526                         for(i=0;i<NUMVERTICES;i++) vzstokes[i]=vzstokes_ptr[i];
    6527                 }
    6528                 else _error_("Cannot compute Vz as VzStokes in not present in PattynStokes element");
    6529                 for(i=0;i<NUMVERTICES;i++){
    6530                         vzpattyn[i]=vz[i];
    6531                         vz[i]=vzpattyn[i]+vzstokes[i];
    6532                 }
    6533         }
    6534         else if(approximation==MacAyealStokesApproximationEnum){
    6535                 Input* vzstokes_input=inputs->GetInput(VzStokesEnum);
    6536                 if (vzstokes_input){
    6537                         if (vzstokes_input->Enum()!=PentaVertexInputEnum) _error_("Cannot compute Vel as VzStokes is of type %s",EnumToStringx(vy_input->Enum()));
    6538                         vzstokes_input->GetValuesPtr(&vzstokes_ptr,&dummy);
    6539                         for(i=0;i<NUMVERTICES;i++) vzstokes[i]=vzstokes_ptr[i];
    6540                 }
    6541                 else _error_("Cannot compute Vz as VzStokes in not present in MacAyealStokes element");
    6542                 for(i=0;i<NUMVERTICES;i++){
    6543                         vzmacayeal[i]=vz[i];
    6544                         vz[i]=vzmacayeal[i]+vzstokes[i];
    6545                 }
    6546         }
    6547 
    6548         /*Now Compute vel*/
    6549         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);
    6550 
    6551         /*For pressure: we have not computed pressure in this analysis, for this element. We are in 3D,
    6552          *so the pressure is just the pressure at the z elevation: except it this is a PattynStokes element */
    6553         if(approximation!=PattynStokesApproximationEnum &&  approximation!=MacAyealStokesApproximationEnum){
    6554                 rho_ice=matpar->GetRhoIce();
    6555                 g=matpar->GetG();
    6556                 GetParameterListOnVertices(&surface[0],SurfaceEnum);
    6557                 for(i=0;i<NUMVERTICES;i++) pressure[i]=rho_ice*g*(surface[i]-xyz_list[i][2]);
    6558         }
    6559 
    6560         /*Now, we have to move the previous Vz inputs to old
    6561          * status, otherwise, we'll wipe them off and add the new inputs: */
    6562         this->inputs->ChangeEnum(VzEnum,VzPicardEnum);
    6563 
    6564         if(approximation!=PattynStokesApproximationEnum && approximation!=MacAyealStokesApproximationEnum){
    6565                 this->inputs->ChangeEnum(PressureEnum,PressurePicardEnum);
    6566                 this->inputs->AddInput(new PentaVertexInput(PressureEnum,pressure));
    6567         }
    6568         else if(approximation==PattynStokesApproximationEnum){
    6569                 this->inputs->AddInput(new PentaVertexInput(VzPattynEnum,vzpattyn));
    6570         }
    6571         else if(approximation==MacAyealStokesApproximationEnum){
    6572                 this->inputs->AddInput(new PentaVertexInput(VzMacAyealEnum,vzmacayeal));
    6573         }
    6574 
    6575         this->inputs->AddInput(new PentaVertexInput(VzEnum,vz));
    6576         this->inputs->AddInput(new PentaVertexInput(VelEnum,vel));
    6577 
    6578         /*Free ressources:*/
    6579         xfree((void**)&doflist);
    6580 }
    6581 /*}}}*/
    6582 /*FUNCTION Penta::InputUpdateFromSolutionDiagnosticStokes {{{1*/
    6583 void  Penta::InputUpdateFromSolutionDiagnosticStokes(double* solution){
    6584        
    6585         const int numdof=NDOF4*NUMVERTICES;
    6586 
    6587         int     i;
    6588         double  values[numdof];
    6589         double  vx[NUMVERTICES];
    6590         double  vy[NUMVERTICES];
    6591         double  vz[NUMVERTICES];
    6592         double  vel[NUMVERTICES];
    6593         double  pressure[NUMVERTICES];
    6594         double  stokesreconditioning;
    6595         int*    doflist=NULL;
    6596 
    6597         /*Get dof list: */
    6598         GetDofList(&doflist,StokesApproximationEnum,GsetEnum);
    6599 
    6600         /*Use the dof list to index into the solution vector: */
    6601         for(i=0;i<numdof;i++) values[i]=solution[doflist[i]];
    6602 
    6603         /*Ok, we have vx and vy in values, fill in all arrays: */
    6604         for(i=0;i<NUMVERTICES;i++){
    6605                 vx[i]=values[i*NDOF4+0];
    6606                 vy[i]=values[i*NDOF4+1];
    6607                 vz[i]=values[i*NDOF4+2];
    6608                 pressure[i]=values[i*NDOF4+3];
    6609 
    6610                 /*Check solution*/
    6611                 if(isnan(vx[i]))       _error_("NaN found in solution vector");
    6612                 if(isnan(vy[i]))       _error_("NaN found in solution vector");
    6613                 if(isnan(vz[i]))       _error_("NaN found in solution vector");
    6614                 if(isnan(pressure[i])) _error_("NaN found in solution vector");
    6615         }
    6616 
    6617         /*Recondition pressure and compute vel: */
    6618         this->parameters->FindParam(&stokesreconditioning,DiagnosticStokesreconditioningEnum);
    6619         for(i=0;i<NUMVERTICES;i++) pressure[i]=pressure[i]*stokesreconditioning;
    6620         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);
    6621        
    6622         /*Now, we have to move the previous inputs  to old
    6623          * status, otherwise, we'll wipe them off: */
    6624         this->inputs->ChangeEnum(VxEnum,VxPicardEnum);
    6625         this->inputs->ChangeEnum(VyEnum,VyPicardEnum);
    6626         this->inputs->ChangeEnum(VzEnum,VzPicardEnum);
    6627         this->inputs->ChangeEnum(PressureEnum,PressurePicardEnum);
    6628 
    6629         /*Add vx and vy as inputs to the tria element: */
    6630         this->inputs->AddInput(new PentaVertexInput(VxEnum,vx));
    6631         this->inputs->AddInput(new PentaVertexInput(VyEnum,vy));
    6632         this->inputs->AddInput(new PentaVertexInput(VzEnum,vz));
    6633         this->inputs->AddInput(new PentaVertexInput(VelEnum,vel));
    6634         this->inputs->AddInput(new PentaVertexInput(PressureEnum,pressure));
    6635 
    6636         /*Free ressources:*/
    6637         xfree((void**)&doflist);
    66381718}
    66391719/*}}}*/
     
    77382818}
    77392819/*}}}*/
     2820
     2821#ifdef _HAVE_THERMAL_
     2822/*FUNCTION Penta::CreateKMatrixEnthalpy {{{1*/
     2823ElementMatrix* Penta::CreateKMatrixEnthalpy(void){
     2824       
     2825        /*compute all stiffness matrices for this element*/
     2826        ElementMatrix* Ke1=CreateKMatrixEnthalpyVolume();
     2827        ElementMatrix* Ke2=CreateKMatrixEnthalpyShelf();
     2828        ElementMatrix* Ke =new ElementMatrix(Ke1,Ke2);
     2829       
     2830        /*clean-up and return*/
     2831        delete Ke1;
     2832        delete Ke2;
     2833        return Ke;
     2834}
     2835/*}}}*/
     2836/*FUNCTION Penta::CreateKMatrixEnthalpyVolume {{{1*/
     2837ElementMatrix* Penta::CreateKMatrixEnthalpyVolume(void){
     2838
     2839        /*Constants*/
     2840        const int    numdof=NDOF1*NUMVERTICES;
     2841
     2842        /*Intermediaries */
     2843        int        stabilization;
     2844        int        i,j,ig,found=0;
     2845        double     Jdet,u,v,w,um,vm,wm;
     2846        double     gravity,rho_ice,rho_water;
     2847        double     epsvel=2.220446049250313e-16;
     2848        double     heatcapacity,thermalconductivity,dt;
     2849        double     pressure,enthalpy;
     2850        double     latentheat,kappa;
     2851        double     tau_parameter,diameter;
     2852        double     xyz_list[NUMVERTICES][3];
     2853        double     B[3][numdof];
     2854        double     Bprime[3][numdof];
     2855        double     B_conduct[3][numdof];
     2856        double     B_advec[3][numdof];
     2857        double     B_stab[2][numdof];
     2858        double     Bprime_advec[3][numdof];
     2859        double     L[numdof];
     2860        double     dbasis[3][6];
     2861        double     D_scalar_conduct,D_scalar_advec;
     2862        double     D_scalar_trans,D_scalar_stab;
     2863        double     D[3][3];
     2864        double     K[2][2]={0.0};
     2865        Tria*      tria=NULL;
     2866        GaussPenta *gauss=NULL;
     2867
     2868        /*Initialize Element matrix*/
     2869        ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,NoneApproximationEnum);
     2870
     2871        /*Retrieve all inputs and parameters*/
     2872        GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
     2873        rho_water=matpar->GetRhoWater();
     2874        rho_ice=matpar->GetRhoIce();
     2875        gravity=matpar->GetG();
     2876        heatcapacity=matpar->GetHeatCapacity();
     2877        latentheat=matpar->GetLatentHeat();
     2878        thermalconductivity=matpar->GetThermalConductivity();
     2879        this->parameters->FindParam(&dt,TimesteppingTimeStepEnum);
     2880        this->parameters->FindParam(&stabilization,ThermalStabilizationEnum);
     2881        Input* pressure_input=inputs->GetInput(PressureEnum);      _assert_(pressure_input);
     2882        Input* enthalpy_input=inputs->GetInput(EnthalpyEnum);      _assert_(enthalpy_input);
     2883        Input* vx_input=inputs->GetInput(VxEnum);                  _assert_(vx_input);
     2884        Input* vy_input=inputs->GetInput(VyEnum);                  _assert_(vy_input);
     2885        Input* vz_input=inputs->GetInput(VzEnum);                  _assert_(vz_input);
     2886        Input* vxm_input=inputs->GetInput(VxMeshEnum);             _assert_(vxm_input);
     2887        Input* vym_input=inputs->GetInput(VyMeshEnum);             _assert_(vym_input);
     2888        Input* vzm_input=inputs->GetInput(VzMeshEnum);             _assert_(vzm_input);
     2889        if (stabilization==2) diameter=MinEdgeLength(xyz_list);
     2890
     2891        /* Start  looping on the number of gaussian points: */
     2892        gauss=new GaussPenta(2,2);
     2893        for (ig=gauss->begin();ig<gauss->end();ig++){
     2894
     2895                gauss->GaussPoint(ig);
     2896
     2897                GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss);
     2898
     2899                /*Conduction: */ 
     2900                /*Need to change that depending on enthalpy value -> cold or temperate ice: */ 
     2901
     2902                GetBConduct(&B_conduct[0][0],&xyz_list[0][0],gauss);
     2903
     2904                enthalpy_input->GetParameterValue(&enthalpy, gauss);
     2905                pressure_input->GetParameterValue(&pressure, gauss);
     2906                kappa=matpar->GetEnthalpyDiffusionParameter(enthalpy,pressure);
     2907                D_scalar_conduct=gauss->weight*Jdet*kappa;
     2908                if(dt) D_scalar_conduct=D_scalar_conduct*dt;
     2909
     2910                D[0][0]=D_scalar_conduct; D[0][1]=0; D[0][2]=0;
     2911                D[1][0]=0; D[1][1]=D_scalar_conduct; D[1][2]=0;
     2912                D[2][0]=0; D[2][1]=0; D[2][2]=D_scalar_conduct;
     2913
     2914                TripleMultiply(&B_conduct[0][0],3,numdof,1,
     2915                                        &D[0][0],3,3,0,
     2916                                        &B_conduct[0][0],3,numdof,0,
     2917                                        &Ke->values[0],1);
     2918
     2919                /*Advection: */
     2920
     2921                GetBAdvec(&B_advec[0][0],&xyz_list[0][0],gauss);
     2922                GetBprimeAdvec(&Bprime_advec[0][0],&xyz_list[0][0],gauss);
     2923
     2924                vx_input->GetParameterValue(&u, gauss);
     2925                vy_input->GetParameterValue(&v, gauss);
     2926                vz_input->GetParameterValue(&w, gauss);
     2927                vxm_input->GetParameterValue(&um,gauss);
     2928                vym_input->GetParameterValue(&vm,gauss);
     2929                vzm_input->GetParameterValue(&wm,gauss);
     2930
     2931                D_scalar_advec=gauss->weight*Jdet;
     2932                if(dt) D_scalar_advec=D_scalar_advec*dt;
     2933
     2934                D[0][0]=D_scalar_advec*(u-um);D[0][1]=0;                    D[0][2]=0;
     2935                D[1][0]=0;                    D[1][1]=D_scalar_advec*(v-vm);D[1][2]=0;
     2936                D[2][0]=0;                    D[2][1]=0;                    D[2][2]=D_scalar_advec*(w-wm);
     2937
     2938                TripleMultiply(&B_advec[0][0],3,numdof,1,
     2939                                        &D[0][0],3,3,0,
     2940                                        &Bprime_advec[0][0],3,numdof,0,
     2941                                        &Ke->values[0],1);
     2942
     2943                /*Transient: */
     2944
     2945                if(dt){
     2946                        GetNodalFunctionsP1(&L[0], gauss);
     2947                        D_scalar_trans=gauss->weight*Jdet;
     2948                        D_scalar_trans=D_scalar_trans;
     2949
     2950                        TripleMultiply(&L[0],numdof,1,0,
     2951                                                &D_scalar_trans,1,1,0,
     2952                                                &L[0],1,numdof,0,
     2953                                                &Ke->values[0],1);
     2954                }
     2955
     2956                /*Artifficial diffusivity*/
     2957
     2958                if(stabilization==1){
     2959                        /*Build K: */
     2960                        D_scalar_stab=gauss->weight*Jdet/(pow(u-um,2)+pow(v-vm,2)+epsvel);
     2961                        if(dt) D_scalar_stab=D_scalar_stab*dt;
     2962                        K[0][0]=D_scalar_stab*pow(u,2);       K[0][1]=D_scalar_stab*fabs(u)*fabs(v);
     2963                        K[1][0]=D_scalar_stab*fabs(u)*fabs(v);K[1][1]=D_scalar_stab*pow(v,2);
     2964
     2965                        GetBArtdiff(&B_stab[0][0],&xyz_list[0][0],gauss);
     2966
     2967                        TripleMultiply(&B_stab[0][0],2,numdof,1,
     2968                                                &K[0][0],2,2,0,
     2969                                                &B_stab[0][0],2,numdof,0,
     2970                                                &Ke->values[0],1);
     2971                }
     2972                else if(stabilization==2){
     2973
     2974                        GetNodalFunctionsP1Derivatives(&dbasis[0][0],&xyz_list[0][0], gauss);
     2975
     2976                        tau_parameter=GetStabilizationParameter(u-um,v-vm,w-wm,diameter,rho_ice,heatcapacity,thermalconductivity);
     2977
     2978                        for(i=0;i<numdof;i++){
     2979                                for(j=0;j<numdof;j++){
     2980                                        Ke->values[i*numdof+j]+=tau_parameter*D_scalar_advec*
     2981                                          ((u-um)*dbasis[0][i]+(v-vm)*dbasis[1][i]+(w-wm)*dbasis[2][i])*((u-um)*dbasis[0][j]+(v-vm)*dbasis[1][j]+(w-wm)*dbasis[2][j]);
     2982                                }
     2983                        }
     2984                        if(dt){
     2985                                for(i=0;i<numdof;i++){
     2986                                        for(j=0;j<numdof;j++){
     2987                                                Ke->values[i*numdof+j]+=tau_parameter*D_scalar_trans*L[j]*((u-um)*dbasis[0][i]+(v-vm)*dbasis[1][i]+(w-wm)*dbasis[2][i]);
     2988                                        }
     2989                                }
     2990                        }
     2991                }
     2992        }
     2993
     2994        /*Clean up and return*/
     2995        delete gauss;
     2996        return Ke;
     2997}
     2998/*}}}*/
     2999/*FUNCTION Penta::CreateKMatrixEnthalpyShelf {{{1*/
     3000ElementMatrix* Penta::CreateKMatrixEnthalpyShelf(void){
     3001
     3002        /*Constants*/
     3003        const int    numdof=NDOF1*NUMVERTICES;
     3004
     3005        /*Intermediaries */
     3006        int       i,j,ig;
     3007        double    mixed_layer_capacity,thermal_exchange_velocity;
     3008        double    rho_ice,rho_water,heatcapacity;
     3009        double    Jdet2d,dt;
     3010        double    xyz_list[NUMVERTICES][3];
     3011        double   xyz_list_tria[NUMVERTICES2D][3];
     3012        double    basis[NUMVERTICES];
     3013        double    D_scalar;
     3014        GaussPenta *gauss=NULL;
     3015
     3016        /*Initialize Element matrix and return if necessary*/
     3017        if (!IsOnBed() || !IsOnShelf()) return NULL;
     3018        ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,NoneApproximationEnum);
     3019
     3020        /*Retrieve all inputs and parameters*/
     3021        this->parameters->FindParam(&dt,TimesteppingTimeStepEnum);
     3022        mixed_layer_capacity=matpar->GetMixedLayerCapacity();
     3023        thermal_exchange_velocity=matpar->GetThermalExchangeVelocity();
     3024        rho_water=matpar->GetRhoWater();
     3025        rho_ice=matpar->GetRhoIce();
     3026        heatcapacity=matpar->GetHeatCapacity();
     3027        GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
     3028        for(i=0;i<NUMVERTICES2D;i++) for(j=0;j<3;j++) xyz_list_tria[i][j]=xyz_list[i][j];
     3029
     3030        /* Start looping on the number of gauss (nodes on the bedrock) */
     3031        gauss=new GaussPenta(0,1,2,2);
     3032        for (ig=gauss->begin();ig<gauss->end();ig++){
     3033
     3034                gauss->GaussPoint(ig);
     3035               
     3036                GetTriaJacobianDeterminant(&Jdet2d, &xyz_list_tria[0][0], gauss);
     3037                GetNodalFunctionsP1(&basis[0], gauss);
     3038                               
     3039                D_scalar=gauss->weight*Jdet2d*rho_water*mixed_layer_capacity*thermal_exchange_velocity/(rho_ice*heatcapacity);
     3040                if(dt) D_scalar=dt*D_scalar;
     3041
     3042                TripleMultiply(&basis[0],numdof,1,0,
     3043                                        &D_scalar,1,1,0,
     3044                                        &basis[0],1,numdof,0,
     3045                                        &Ke->values[0],1);
     3046        }
     3047       
     3048        /*Clean up and return*/
     3049        delete gauss;
     3050        return Ke;
     3051}
     3052/*}}}*/
     3053/*FUNCTION Penta::CreateKMatrixMelting {{{1*/
     3054ElementMatrix* Penta::CreateKMatrixMelting(void){
     3055
     3056        if (!IsOnBed()) return NULL;
     3057
     3058        Tria* tria=(Tria*)SpawnTria(0,1,2); //nodes 0, 1 and 2 make the new tria.
     3059        ElementMatrix* Ke=tria->CreateKMatrixMelting();
     3060
     3061        delete tria->matice; delete tria;
     3062        return Ke;
     3063}
     3064/*}}}*/
     3065/*FUNCTION Penta::CreateKMatrixThermal {{{1*/
     3066ElementMatrix* Penta::CreateKMatrixThermal(void){
     3067       
     3068        /*compute all stiffness matrices for this element*/
     3069        ElementMatrix* Ke1=CreateKMatrixThermalVolume();
     3070        ElementMatrix* Ke2=CreateKMatrixThermalShelf();
     3071        ElementMatrix* Ke =new ElementMatrix(Ke1,Ke2);
     3072       
     3073        /*clean-up and return*/
     3074        delete Ke1;
     3075        delete Ke2;
     3076        return Ke;
     3077}
     3078/*}}}*/
     3079/*FUNCTION Penta::CreateKMatrixThermalVolume {{{1*/
     3080ElementMatrix* Penta::CreateKMatrixThermalVolume(void){
     3081
     3082        /*Constants*/
     3083        const int    numdof=NDOF1*NUMVERTICES;
     3084
     3085        /*Intermediaries */
     3086        int        stabilization;
     3087        int        i,j,ig,found=0;
     3088        double     Jdet,u,v,w,um,vm,wm;
     3089        double     epsvel=2.220446049250313e-16;
     3090        double     gravity,rho_ice,rho_water;
     3091        double     heatcapacity,thermalconductivity,dt;
     3092        double     tau_parameter,diameter;
     3093        double     xyz_list[NUMVERTICES][3];
     3094        double     B[3][numdof];
     3095        double     Bprime[3][numdof];
     3096        double     B_conduct[3][numdof];
     3097        double     B_advec[3][numdof];
     3098        double     B_stab[2][numdof];
     3099        double     Bprime_advec[3][numdof];
     3100        double     L[numdof];
     3101        double     dbasis[3][6];
     3102        double     D_scalar_conduct,D_scalar_advec;
     3103        double     D_scalar_trans,D_scalar_stab;
     3104        double     D[3][3];
     3105        double     K[2][2]={0.0};
     3106        Tria*      tria=NULL;
     3107        GaussPenta *gauss=NULL;
     3108
     3109        /*Initialize Element matrix*/
     3110        ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,NoneApproximationEnum);
     3111
     3112        /*Retrieve all inputs and parameters*/
     3113        GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
     3114        rho_water=matpar->GetRhoWater();
     3115        rho_ice=matpar->GetRhoIce();
     3116        gravity=matpar->GetG();
     3117        heatcapacity=matpar->GetHeatCapacity();
     3118        thermalconductivity=matpar->GetThermalConductivity();
     3119        this->parameters->FindParam(&dt,TimesteppingTimeStepEnum);
     3120        this->parameters->FindParam(&stabilization,ThermalStabilizationEnum);
     3121        Input* vx_input=inputs->GetInput(VxEnum);      _assert_(vx_input);
     3122        Input* vy_input=inputs->GetInput(VyEnum);      _assert_(vy_input);
     3123        Input* vz_input=inputs->GetInput(VzEnum);      _assert_(vz_input);
     3124        Input* vxm_input=inputs->GetInput(VxMeshEnum); _assert_(vxm_input);
     3125        Input* vym_input=inputs->GetInput(VyMeshEnum); _assert_(vym_input);
     3126        Input* vzm_input=inputs->GetInput(VzMeshEnum); _assert_(vzm_input);
     3127        if (stabilization==2) diameter=MinEdgeLength(xyz_list);
     3128
     3129        /* Start  looping on the number of gaussian points: */
     3130        gauss=new GaussPenta(2,2);
     3131        for (ig=gauss->begin();ig<gauss->end();ig++){
     3132
     3133                gauss->GaussPoint(ig);
     3134
     3135                GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss);
     3136
     3137                /*Conduction: */
     3138
     3139                GetBConduct(&B_conduct[0][0],&xyz_list[0][0],gauss);
     3140
     3141                D_scalar_conduct=gauss->weight*Jdet*(thermalconductivity/(rho_ice*heatcapacity));
     3142                if(dt) D_scalar_conduct=D_scalar_conduct*dt;
     3143
     3144                D[0][0]=D_scalar_conduct; D[0][1]=0; D[0][2]=0;
     3145                D[1][0]=0; D[1][1]=D_scalar_conduct; D[1][2]=0;
     3146                D[2][0]=0; D[2][1]=0; D[2][2]=D_scalar_conduct;
     3147
     3148                TripleMultiply(&B_conduct[0][0],3,numdof,1,
     3149                                        &D[0][0],3,3,0,
     3150                                        &B_conduct[0][0],3,numdof,0,
     3151                                        &Ke->values[0],1);
     3152
     3153                /*Advection: */
     3154
     3155                GetBAdvec(&B_advec[0][0],&xyz_list[0][0],gauss);
     3156                GetBprimeAdvec(&Bprime_advec[0][0],&xyz_list[0][0],gauss);
     3157
     3158                vx_input->GetParameterValue(&u, gauss);
     3159                vy_input->GetParameterValue(&v, gauss);
     3160                vz_input->GetParameterValue(&w, gauss);
     3161                vxm_input->GetParameterValue(&um,gauss);
     3162                vym_input->GetParameterValue(&vm,gauss);
     3163                vzm_input->GetParameterValue(&wm,gauss);
     3164
     3165                D_scalar_advec=gauss->weight*Jdet;
     3166                if(dt) D_scalar_advec=D_scalar_advec*dt;
     3167
     3168                D[0][0]=D_scalar_advec*(u-um);D[0][1]=0;                    D[0][2]=0;
     3169                D[1][0]=0;                    D[1][1]=D_scalar_advec*(v-vm);D[1][2]=0;
     3170                D[2][0]=0;                    D[2][1]=0;                    D[2][2]=D_scalar_advec*(w-wm);
     3171
     3172                TripleMultiply(&B_advec[0][0],3,numdof,1,
     3173                                        &D[0][0],3,3,0,
     3174                                        &Bprime_advec[0][0],3,numdof,0,
     3175                                        &Ke->values[0],1);
     3176
     3177                /*Transient: */
     3178
     3179                if(dt){
     3180                        GetNodalFunctionsP1(&L[0], gauss);
     3181                        D_scalar_trans=gauss->weight*Jdet;
     3182                        D_scalar_trans=D_scalar_trans;
     3183
     3184                        TripleMultiply(&L[0],numdof,1,0,
     3185                                                &D_scalar_trans,1,1,0,
     3186                                                &L[0],1,numdof,0,
     3187                                                &Ke->values[0],1);
     3188                }
     3189
     3190                /*Artifficial diffusivity*/
     3191
     3192                if(stabilization==1){
     3193                        /*Build K: */
     3194                        D_scalar_stab=gauss->weight*Jdet/(pow(u-um,2)+pow(v-vm,2)+epsvel);
     3195                        if(dt) D_scalar_stab=D_scalar_stab*dt;
     3196                        K[0][0]=D_scalar_stab*pow(u,2);       K[0][1]=D_scalar_stab*fabs(u)*fabs(v);
     3197                        K[1][0]=D_scalar_stab*fabs(u)*fabs(v);K[1][1]=D_scalar_stab*pow(v,2);
     3198
     3199                        GetBArtdiff(&B_stab[0][0],&xyz_list[0][0],gauss);
     3200
     3201                        TripleMultiply(&B_stab[0][0],2,numdof,1,
     3202                                                &K[0][0],2,2,0,
     3203                                                &B_stab[0][0],2,numdof,0,
     3204                                                &Ke->values[0],1);
     3205                }
     3206                else if(stabilization==2){
     3207
     3208                        GetNodalFunctionsP1Derivatives(&dbasis[0][0],&xyz_list[0][0], gauss);
     3209
     3210                        tau_parameter=GetStabilizationParameter(u-um,v-vm,w-wm,diameter,rho_ice,heatcapacity,thermalconductivity);
     3211
     3212                        for(i=0;i<numdof;i++){
     3213                                for(j=0;j<numdof;j++){
     3214                                        Ke->values[i*numdof+j]+=tau_parameter*D_scalar_advec*
     3215                                          ((u-um)*dbasis[0][i]+(v-vm)*dbasis[1][i]+(w-wm)*dbasis[2][i])*((u-um)*dbasis[0][j]+(v-vm)*dbasis[1][j]+(w-wm)*dbasis[2][j]);
     3216                                }
     3217                        }
     3218                        if(dt){
     3219                                for(i=0;i<numdof;i++){
     3220                                        for(j=0;j<numdof;j++){
     3221                                                Ke->values[i*numdof+j]+=tau_parameter*D_scalar_trans*L[j]*((u-um)*dbasis[0][i]+(v-vm)*dbasis[1][i]+(w-wm)*dbasis[2][i]);
     3222                                        }
     3223                                }
     3224                        }
     3225                }
     3226        }
     3227
     3228        /*Clean up and return*/
     3229        delete gauss;
     3230        return Ke;
     3231}
     3232/*}}}*/
     3233/*FUNCTION Penta::CreateKMatrixThermalShelf {{{1*/
     3234ElementMatrix* Penta::CreateKMatrixThermalShelf(void){
     3235
     3236
     3237        /*Constants*/
     3238        const int    numdof=NDOF1*NUMVERTICES;
     3239
     3240        /*Intermediaries */
     3241        int       i,j,ig;
     3242        double    mixed_layer_capacity,thermal_exchange_velocity;
     3243        double    rho_ice,rho_water,heatcapacity;
     3244        double    Jdet2d,dt;
     3245        double    xyz_list[NUMVERTICES][3];
     3246        double   xyz_list_tria[NUMVERTICES2D][3];
     3247        double    basis[NUMVERTICES];
     3248        double    D_scalar;
     3249        GaussPenta *gauss=NULL;
     3250
     3251        /*Initialize Element matrix and return if necessary*/
     3252        if (!IsOnBed() || !IsOnShelf()) return NULL;
     3253        ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,NoneApproximationEnum);
     3254
     3255        /*Retrieve all inputs and parameters*/
     3256        this->parameters->FindParam(&dt,TimesteppingTimeStepEnum);
     3257        mixed_layer_capacity=matpar->GetMixedLayerCapacity();
     3258        thermal_exchange_velocity=matpar->GetThermalExchangeVelocity();
     3259        rho_water=matpar->GetRhoWater();
     3260        rho_ice=matpar->GetRhoIce();
     3261        heatcapacity=matpar->GetHeatCapacity();
     3262        GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
     3263        for(i=0;i<NUMVERTICES2D;i++) for(j=0;j<3;j++) xyz_list_tria[i][j]=xyz_list[i][j];
     3264
     3265        /* Start looping on the number of gauss (nodes on the bedrock) */
     3266        gauss=new GaussPenta(0,1,2,2);
     3267        for (ig=gauss->begin();ig<gauss->end();ig++){
     3268
     3269                gauss->GaussPoint(ig);
     3270               
     3271                GetTriaJacobianDeterminant(&Jdet2d, &xyz_list_tria[0][0], gauss);
     3272                GetNodalFunctionsP1(&basis[0], gauss);
     3273                               
     3274                D_scalar=gauss->weight*Jdet2d*rho_water*mixed_layer_capacity*thermal_exchange_velocity/(heatcapacity*rho_ice);
     3275                if(dt) D_scalar=dt*D_scalar;
     3276
     3277                TripleMultiply(&basis[0],numdof,1,0,
     3278                                        &D_scalar,1,1,0,
     3279                                        &basis[0],1,numdof,0,
     3280                                        &Ke->values[0],1);
     3281        }
     3282       
     3283        /*Clean up and return*/
     3284        delete gauss;
     3285        return Ke;
     3286}
     3287/*}}}*/
     3288/*FUNCTION Penta::CreatePVectorEnthalpy {{{1*/
     3289ElementVector* Penta::CreatePVectorEnthalpy(void){
     3290
     3291        /*compute all load vectors for this element*/
     3292        ElementVector* pe1=CreatePVectorEnthalpyVolume();
     3293        ElementVector* pe2=CreatePVectorEnthalpySheet();
     3294        ElementVector* pe3=CreatePVectorEnthalpyShelf();
     3295        ElementVector* pe =new ElementVector(pe1,pe2,pe3);
     3296
     3297        /*clean-up and return*/
     3298        delete pe1;
     3299        delete pe2;
     3300        delete pe3;
     3301        return pe;
     3302}
     3303/*}}}*/
     3304/*FUNCTION Penta::CreatePVectorEnthalpyVolume {{{1*/
     3305ElementVector* Penta::CreatePVectorEnthalpyVolume(void){
     3306
     3307        /*Constants*/
     3308        const int  numdof=NUMVERTICES*NDOF1;
     3309
     3310        /*Intermediaries*/
     3311        int    i,j,ig,found=0;
     3312        int    friction_type,stabilization;
     3313        double Jdet,phi,dt;
     3314        double rho_ice,heatcapacity;
     3315        double thermalconductivity;
     3316        double viscosity,temperature;
     3317        double tau_parameter,diameter;
     3318        double u,v,w;
     3319        double scalar_def,scalar_transient;
     3320        double temperature_list[NUMVERTICES];
     3321        double xyz_list[NUMVERTICES][3];
     3322        double L[numdof];
     3323        double dbasis[3][6];
     3324        double epsilon[6];
     3325        GaussPenta *gauss=NULL;
     3326
     3327        /*Initialize Element vector*/
     3328        ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters);
     3329
     3330        /*Retrieve all inputs and parameters*/
     3331        GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
     3332        rho_ice=matpar->GetRhoIce();
     3333        heatcapacity=matpar->GetHeatCapacity();
     3334        thermalconductivity=matpar->GetThermalConductivity();
     3335        this->parameters->FindParam(&dt,TimesteppingTimeStepEnum);
     3336        this->parameters->FindParam(&stabilization,ThermalStabilizationEnum);
     3337        Input* vx_input=inputs->GetInput(VxEnum); _assert_(vx_input);
     3338        Input* vy_input=inputs->GetInput(VyEnum); _assert_(vy_input);
     3339        Input* vz_input=inputs->GetInput(VzEnum); _assert_(vz_input);
     3340        Input* temperature_input=NULL;
     3341        if (dt) temperature_input=inputs->GetInput(TemperatureEnum); _assert_(inputs);
     3342        if (stabilization==2) diameter=MinEdgeLength(xyz_list);
     3343
     3344        /* Start  looping on the number of gaussian points: */
     3345        gauss=new GaussPenta(2,3);
     3346        for (ig=gauss->begin();ig<gauss->end();ig++){
     3347
     3348                gauss->GaussPoint(ig);
     3349
     3350                GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss);
     3351                GetNodalFunctionsP1(&L[0], gauss);
     3352
     3353                this->GetStrainRate3d(&epsilon[0],&xyz_list[0][0],gauss,vx_input,vy_input,vz_input);
     3354                matice->GetViscosity3dStokes(&viscosity,&epsilon[0]);
     3355                GetPhi(&phi, &epsilon[0], viscosity);
     3356
     3357                scalar_def=phi/(rho_ice)*Jdet*gauss->weight;
     3358                if(dt) scalar_def=scalar_def*dt;
     3359
     3360                for(i=0;i<NUMVERTICES;i++)  pe->values[i]+=scalar_def*L[i];
     3361
     3362                /* Build transient now */
     3363                if(dt){
     3364                        temperature_input->GetParameterValue(&temperature, gauss);
     3365                        scalar_transient=temperature*Jdet*gauss->weight;
     3366                        for(i=0;i<NUMVERTICES;i++)  pe->values[i]+=scalar_transient*L[i];
     3367                }
     3368
     3369                if(stabilization==2){
     3370                        GetNodalFunctionsP1Derivatives(&dbasis[0][0],&xyz_list[0][0], gauss);
     3371
     3372                        vx_input->GetParameterValue(&u, gauss);
     3373                        vy_input->GetParameterValue(&v, gauss);
     3374                        vz_input->GetParameterValue(&w, gauss);
     3375
     3376                        tau_parameter=GetStabilizationParameter(u,v,w,diameter,rho_ice,heatcapacity,thermalconductivity);
     3377
     3378                        for(i=0;i<NUMVERTICES;i++)  pe->values[i]+=tau_parameter*scalar_def*(u*dbasis[0][i]+v*dbasis[1][i]+w*dbasis[2][i]);
     3379                        if(dt){
     3380                                for(i=0;i<NUMVERTICES;i++)  pe->values[i]+=tau_parameter*scalar_transient*(u*dbasis[0][i]+v*dbasis[1][i]+w*dbasis[2][i]);
     3381                        }
     3382                }
     3383        }
     3384
     3385        /*Clean up and return*/
     3386        delete gauss;
     3387        return pe;
     3388}
     3389/*}}}*/
     3390/*FUNCTION Penta::CreatePVectorEnthalpyShelf {{{1*/
     3391ElementVector* Penta::CreatePVectorEnthalpyShelf(void){
     3392
     3393        /*Constants*/
     3394        const int  numdof=NUMVERTICES*NDOF1;
     3395
     3396        /*Intermediaries */
     3397        int        i,j,ig;
     3398        double     Jdet2d;
     3399        double     heatcapacity,h_pmp;
     3400        double     mixed_layer_capacity,thermal_exchange_velocity;
     3401        double     rho_ice,rho_water,pressure,dt,scalar_ocean;
     3402        double     xyz_list[NUMVERTICES][3];
     3403        double     xyz_list_tria[NUMVERTICES2D][3];
     3404        double     basis[NUMVERTICES];
     3405        GaussPenta* gauss=NULL;
     3406
     3407        /*Initialize Element vector*/
     3408        ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters);
     3409
     3410        /* Ice/ocean heat exchange flux on ice shelf base */
     3411        if (!IsOnBed() || !IsOnShelf()) return NULL;
     3412
     3413        /*Retrieve all inputs and parameters*/
     3414        GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
     3415        for(i=0;i<NUMVERTICES2D;i++) for(j=0;j<3;j++) xyz_list_tria[i][j]=xyz_list[i][j];
     3416        mixed_layer_capacity=matpar->GetMixedLayerCapacity();
     3417        thermal_exchange_velocity=matpar->GetThermalExchangeVelocity();
     3418        rho_water=matpar->GetRhoWater();
     3419        rho_ice=matpar->GetRhoIce();
     3420        heatcapacity=matpar->GetHeatCapacity();
     3421        this->parameters->FindParam(&dt,TimesteppingTimeStepEnum);
     3422        Input* pressure_input=inputs->GetInput(PressureEnum); _assert_(pressure_input);
     3423
     3424        /* Start looping on the number of gauss 2d (nodes on the bedrock) */
     3425        gauss=new GaussPenta(0,1,2,2);
     3426        for(ig=gauss->begin();ig<gauss->end();ig++){
     3427
     3428                gauss->GaussPoint(ig);
     3429
     3430                GetTriaJacobianDeterminant(&Jdet2d, &xyz_list_tria[0][0], gauss);
     3431                GetNodalFunctionsP1(&basis[0], gauss);
     3432
     3433                pressure_input->GetParameterValue(&pressure,gauss);
     3434                h_pmp=matpar->PureIceEnthalpy(pressure);
     3435
     3436                scalar_ocean=gauss->weight*Jdet2d*rho_water*mixed_layer_capacity*thermal_exchange_velocity*(h_pmp)/(rho_ice*heatcapacity);
     3437                if(dt) scalar_ocean=dt*scalar_ocean;
     3438
     3439                for(i=0;i<numdof;i++) pe->values[i]+=scalar_ocean*basis[i];
     3440        }
     3441
     3442        /*Clean up and return*/
     3443        delete gauss;
     3444        return pe;
     3445}
     3446/*}}}*/
     3447/*FUNCTION Penta::CreatePVectorEnthalpySheet {{{1*/
     3448ElementVector* Penta::CreatePVectorEnthalpySheet(void){
     3449
     3450        /*Constants*/
     3451        const int  numdof=NUMVERTICES*NDOF1;
     3452
     3453        /*Intermediaries */
     3454        int        i,j,ig;
     3455        int        analysis_type;
     3456        double     xyz_list[NUMVERTICES][3];
     3457        double     xyz_list_tria[NUMVERTICES2D][3]={0.0};
     3458        double     Jdet2d,dt;
     3459        double     rho_ice,heatcapacity,geothermalflux_value;
     3460        double     basalfriction,alpha2,vx,vy;
     3461        double     scalar;
     3462        double     basis[NUMVERTICES];
     3463        Friction*  friction=NULL;
     3464        GaussPenta* gauss=NULL;
     3465
     3466        /* Geothermal flux on ice sheet base and basal friction */
     3467        if (!IsOnBed() || IsOnShelf()) return NULL;
     3468
     3469        /*Initialize Element vector*/
     3470        ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters);
     3471
     3472        /*Retrieve all inputs and parameters*/
     3473        GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
     3474        for(i=0;i<NUMVERTICES2D;i++) for(j=0;j<2;j++) xyz_list_tria[i][j]=xyz_list[i][j];
     3475        parameters->FindParam(&analysis_type,AnalysisTypeEnum);
     3476        rho_ice=matpar->GetRhoIce();
     3477        heatcapacity=matpar->GetHeatCapacity();
     3478        this->parameters->FindParam(&dt,TimesteppingTimeStepEnum);
     3479        Input* vx_input=inputs->GetInput(VxEnum);                         _assert_(vx_input);
     3480        Input* vy_input=inputs->GetInput(VyEnum);                         _assert_(vy_input);
     3481        Input* vz_input=inputs->GetInput(VzEnum);                         _assert_(vz_input);
     3482        Input* geothermalflux_input=inputs->GetInput(BasalforcingsGeothermalfluxEnum); _assert_(geothermalflux_input);
     3483
     3484        /*Build frictoin element, needed later: */
     3485        friction=new Friction("3d",inputs,matpar,analysis_type);
     3486
     3487        /* Start looping on the number of gauss 2d (nodes on the bedrock) */
     3488        gauss=new GaussPenta(0,1,2,2);
     3489        for(ig=gauss->begin();ig<gauss->end();ig++){
     3490
     3491                gauss->GaussPoint(ig);
     3492
     3493                GetTriaJacobianDeterminant(&Jdet2d, &xyz_list_tria[0][0], gauss);
     3494                GetNodalFunctionsP1(&basis[0], gauss);
     3495
     3496                geothermalflux_input->GetParameterValue(&geothermalflux_value,gauss);
     3497                friction->GetAlpha2(&alpha2,gauss,VxEnum,VyEnum,VzEnum);
     3498                vx_input->GetParameterValue(&vx,gauss);
     3499                vy_input->GetParameterValue(&vy,gauss);
     3500                basalfriction=alpha2*(pow(vx,2.0)+pow(vy,2.0));
     3501               
     3502                scalar=gauss->weight*Jdet2d*(basalfriction+geothermalflux_value)/(rho_ice);
     3503                if(dt) scalar=dt*scalar;
     3504
     3505                for(i=0;i<numdof;i++) pe->values[i]+=scalar*basis[i];
     3506        }
     3507
     3508        /*Clean up and return*/
     3509        delete gauss;
     3510        delete friction;
     3511        return pe;
     3512}
     3513/*}}}*/
     3514/*FUNCTION Penta::CreatePVectorMelting {{{1*/
     3515ElementVector* Penta::CreatePVectorMelting(void){
     3516        return NULL;
     3517}
     3518/*}}}*/
     3519/*FUNCTION Penta::CreatePVectorThermal {{{1*/
     3520ElementVector* Penta::CreatePVectorThermal(void){
     3521
     3522        /*compute all load vectors for this element*/
     3523        ElementVector* pe1=CreatePVectorThermalVolume();
     3524        ElementVector* pe2=CreatePVectorThermalSheet();
     3525        ElementVector* pe3=CreatePVectorThermalShelf();
     3526        ElementVector* pe =new ElementVector(pe1,pe2,pe3);
     3527
     3528        /*clean-up and return*/
     3529        delete pe1;
     3530        delete pe2;
     3531        delete pe3;
     3532        return pe;
     3533}
     3534/*}}}*/
     3535/*FUNCTION Penta::CreatePVectorThermalVolume {{{1*/
     3536ElementVector* Penta::CreatePVectorThermalVolume(void){
     3537
     3538        /*Constants*/
     3539        const int  numdof=NUMVERTICES*NDOF1;
     3540
     3541        /*Intermediaries*/
     3542        int    i,j,ig,found=0;
     3543        int    friction_type,stabilization;
     3544        double Jdet,phi,dt;
     3545        double rho_ice,heatcapacity;
     3546        double thermalconductivity;
     3547        double viscosity,temperature;
     3548        double tau_parameter,diameter;
     3549        double u,v,w;
     3550        double scalar_def,scalar_transient;
     3551        double temperature_list[NUMVERTICES];
     3552        double xyz_list[NUMVERTICES][3];
     3553        double L[numdof];
     3554        double dbasis[3][6];
     3555        double epsilon[6];
     3556        GaussPenta *gauss=NULL;
     3557
     3558        /*Initialize Element vector*/
     3559        ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters);
     3560
     3561        /*Retrieve all inputs and parameters*/
     3562        GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
     3563        rho_ice=matpar->GetRhoIce();
     3564        heatcapacity=matpar->GetHeatCapacity();
     3565        thermalconductivity=matpar->GetThermalConductivity();
     3566        this->parameters->FindParam(&dt,TimesteppingTimeStepEnum);
     3567        this->parameters->FindParam(&stabilization,ThermalStabilizationEnum);
     3568        Input* vx_input=inputs->GetInput(VxEnum); _assert_(vx_input);
     3569        Input* vy_input=inputs->GetInput(VyEnum); _assert_(vy_input);
     3570        Input* vz_input=inputs->GetInput(VzEnum); _assert_(vz_input);
     3571        Input* temperature_input=NULL;
     3572        if (dt) temperature_input=inputs->GetInput(TemperatureEnum); _assert_(inputs);
     3573        if (stabilization==2) diameter=MinEdgeLength(xyz_list);
     3574
     3575        /* Start  looping on the number of gaussian points: */
     3576        gauss=new GaussPenta(2,3);
     3577        for (ig=gauss->begin();ig<gauss->end();ig++){
     3578
     3579                gauss->GaussPoint(ig);
     3580
     3581                GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss);
     3582                GetNodalFunctionsP1(&L[0], gauss);
     3583
     3584                this->GetStrainRate3d(&epsilon[0],&xyz_list[0][0],gauss,vx_input,vy_input,vz_input);
     3585                matice->GetViscosity3dStokes(&viscosity,&epsilon[0]);
     3586                GetPhi(&phi, &epsilon[0], viscosity);
     3587
     3588                scalar_def=phi/(rho_ice*heatcapacity)*Jdet*gauss->weight;
     3589                if(dt) scalar_def=scalar_def*dt;
     3590
     3591                for(i=0;i<NUMVERTICES;i++)  pe->values[i]+=scalar_def*L[i];
     3592
     3593                /* Build transient now */
     3594                if(dt){
     3595                        temperature_input->GetParameterValue(&temperature, gauss);
     3596                        scalar_transient=temperature*Jdet*gauss->weight;
     3597                        for(i=0;i<NUMVERTICES;i++)  pe->values[i]+=scalar_transient*L[i];
     3598                }
     3599
     3600                if(stabilization==2){
     3601                        GetNodalFunctionsP1Derivatives(&dbasis[0][0],&xyz_list[0][0], gauss);
     3602
     3603                        vx_input->GetParameterValue(&u, gauss);
     3604                        vy_input->GetParameterValue(&v, gauss);
     3605                        vz_input->GetParameterValue(&w, gauss);
     3606
     3607                        tau_parameter=GetStabilizationParameter(u,v,w,diameter,rho_ice,heatcapacity,thermalconductivity);
     3608
     3609                        for(i=0;i<NUMVERTICES;i++)  pe->values[i]+=tau_parameter*scalar_def*(u*dbasis[0][i]+v*dbasis[1][i]+w*dbasis[2][i]);
     3610                        if(dt){
     3611                                for(i=0;i<NUMVERTICES;i++)  pe->values[i]+=tau_parameter*scalar_transient*(u*dbasis[0][i]+v*dbasis[1][i]+w*dbasis[2][i]);
     3612                        }
     3613                }
     3614        }
     3615
     3616        /*Clean up and return*/
     3617        delete gauss;
     3618        return pe;
     3619}
     3620/*}}}*/
     3621/*FUNCTION Penta::CreatePVectorThermalShelf {{{1*/
     3622ElementVector* Penta::CreatePVectorThermalShelf(void){
     3623
     3624        /*Constants*/
     3625        const int  numdof=NUMVERTICES*NDOF1;
     3626
     3627        /*Intermediaries */
     3628        int        i,j,ig;
     3629        double     Jdet2d;
     3630        double     mixed_layer_capacity,thermal_exchange_velocity;
     3631        double     rho_ice,rho_water,pressure,dt,scalar_ocean;
     3632        double     heatcapacity,t_pmp;
     3633        double     xyz_list[NUMVERTICES][3];
     3634        double     xyz_list_tria[NUMVERTICES2D][3];
     3635        double     basis[NUMVERTICES];
     3636        GaussPenta* gauss=NULL;
     3637
     3638        /* Ice/ocean heat exchange flux on ice shelf base */
     3639        if (!IsOnBed() || !IsOnShelf()) return NULL;
     3640
     3641        /*Initialize Element vector*/
     3642        ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters);
     3643
     3644        /*Retrieve all inputs and parameters*/
     3645        GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
     3646        for(i=0;i<NUMVERTICES2D;i++) for(j=0;j<3;j++) xyz_list_tria[i][j]=xyz_list[i][j];
     3647        mixed_layer_capacity=matpar->GetMixedLayerCapacity();
     3648        thermal_exchange_velocity=matpar->GetThermalExchangeVelocity();
     3649        rho_water=matpar->GetRhoWater();
     3650        rho_ice=matpar->GetRhoIce();
     3651        heatcapacity=matpar->GetHeatCapacity();
     3652        this->parameters->FindParam(&dt,TimesteppingTimeStepEnum);
     3653        Input* pressure_input=inputs->GetInput(PressureEnum); _assert_(pressure_input);
     3654
     3655        /* Start looping on the number of gauss 2d (nodes on the bedrock) */
     3656        gauss=new GaussPenta(0,1,2,2);
     3657        for(ig=gauss->begin();ig<gauss->end();ig++){
     3658
     3659                gauss->GaussPoint(ig);
     3660
     3661                GetTriaJacobianDeterminant(&Jdet2d, &xyz_list_tria[0][0], gauss);
     3662                GetNodalFunctionsP1(&basis[0], gauss);
     3663
     3664                pressure_input->GetParameterValue(&pressure,gauss);
     3665                t_pmp=matpar->TMeltingPoint(pressure);
     3666
     3667                scalar_ocean=gauss->weight*Jdet2d*rho_water*mixed_layer_capacity*thermal_exchange_velocity*(t_pmp)/(heatcapacity*rho_ice);
     3668                if(dt) scalar_ocean=dt*scalar_ocean;
     3669
     3670                for(i=0;i<numdof;i++) pe->values[i]+=scalar_ocean*basis[i];
     3671        }
     3672
     3673        /*Clean up and return*/
     3674        delete gauss;
     3675        return pe;
     3676}
     3677/*}}}*/
     3678/*FUNCTION Penta::CreatePVectorThermalSheet {{{1*/
     3679ElementVector* Penta::CreatePVectorThermalSheet(void){
     3680
     3681        /*Constants*/
     3682        const int  numdof=NUMVERTICES*NDOF1;
     3683
     3684        /*Intermediaries */
     3685        int        i,j,ig;
     3686        int        analysis_type;
     3687        double     xyz_list[NUMVERTICES][3];
     3688        double     xyz_list_tria[NUMVERTICES2D][3]={0.0};
     3689        double     Jdet2d,dt;
     3690        double     rho_ice,heatcapacity,geothermalflux_value;
     3691        double     basalfriction,alpha2,vx,vy;
     3692        double     scalar;
     3693        double     basis[NUMVERTICES];
     3694        Friction*  friction=NULL;
     3695        GaussPenta* gauss=NULL;
     3696
     3697        /* Geothermal flux on ice sheet base and basal friction */
     3698        if (!IsOnBed() || IsOnShelf()) return NULL;
     3699
     3700        /*Initialize Element vector*/
     3701        ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters);
     3702
     3703        /*Retrieve all inputs and parameters*/
     3704        GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
     3705        for(i=0;i<NUMVERTICES2D;i++) for(j=0;j<2;j++) xyz_list_tria[i][j]=xyz_list[i][j];
     3706        parameters->FindParam(&analysis_type,AnalysisTypeEnum);
     3707        rho_ice=matpar->GetRhoIce();
     3708        heatcapacity=matpar->GetHeatCapacity();
     3709        this->parameters->FindParam(&dt,TimesteppingTimeStepEnum);
     3710        Input* vx_input=inputs->GetInput(VxEnum);                         _assert_(vx_input);
     3711        Input* vy_input=inputs->GetInput(VyEnum);                         _assert_(vy_input);
     3712        Input* vz_input=inputs->GetInput(VzEnum);                         _assert_(vz_input);
     3713        Input* geothermalflux_input=inputs->GetInput(BasalforcingsGeothermalfluxEnum); _assert_(geothermalflux_input);
     3714
     3715        /*Build frictoin element, needed later: */
     3716        friction=new Friction("3d",inputs,matpar,analysis_type);
     3717
     3718        /* Start looping on the number of gauss 2d (nodes on the bedrock) */
     3719        gauss=new GaussPenta(0,1,2,2);
     3720        for(ig=gauss->begin();ig<gauss->end();ig++){
     3721
     3722                gauss->GaussPoint(ig);
     3723
     3724                GetTriaJacobianDeterminant(&Jdet2d, &xyz_list_tria[0][0], gauss);
     3725                GetNodalFunctionsP1(&basis[0], gauss);
     3726
     3727                geothermalflux_input->GetParameterValue(&geothermalflux_value,gauss);
     3728                friction->GetAlpha2(&alpha2,gauss,VxEnum,VyEnum,VzEnum);
     3729                vx_input->GetParameterValue(&vx,gauss);
     3730                vy_input->GetParameterValue(&vy,gauss);
     3731                basalfriction=alpha2*(pow(vx,2.0)+pow(vy,2.0));
     3732               
     3733                scalar=gauss->weight*Jdet2d*(basalfriction+geothermalflux_value)/(heatcapacity*rho_ice);
     3734                if(dt) scalar=dt*scalar;
     3735
     3736                for(i=0;i<numdof;i++) pe->values[i]+=scalar*basis[i];
     3737        }
     3738
     3739        /*Clean up and return*/
     3740        delete gauss;
     3741        delete friction;
     3742        return pe;
     3743}
     3744/*}}}*/
     3745/*FUNCTION Penta::GetSolutionFromInputsThermal{{{1*/
     3746void  Penta::GetSolutionFromInputsThermal(Vec solution){
     3747
     3748        const int    numdof=NDOF1*NUMVERTICES;
     3749
     3750        int          i;
     3751        int*         doflist=NULL;
     3752        double       values[numdof];
     3753        double       temp;
     3754        GaussPenta   *gauss=NULL;
     3755
     3756        /*Get dof list: */
     3757        GetDofList(&doflist,NoneApproximationEnum,GsetEnum);
     3758        Input* t_input=inputs->GetInput(TemperatureEnum); _assert_(t_input);
     3759
     3760        gauss=new GaussPenta();
     3761        for(i=0;i<NUMVERTICES;i++){
     3762                /*Recover temperature*/
     3763                gauss->GaussVertex(i);
     3764                t_input->GetParameterValue(&temp,gauss);
     3765                values[i]=temp;
     3766        }
     3767
     3768        /*Add value to global vector*/
     3769        VecSetValues(solution,numdof,doflist,(const double*)values,INSERT_VALUES);
     3770
     3771        /*Free ressources:*/
     3772        delete gauss;
     3773        xfree((void**)&doflist);
     3774}
     3775/*}}}*/
     3776/*FUNCTION Penta::GetSolutionFromInputsEnthalpy{{{1*/
     3777void  Penta::GetSolutionFromInputsEnthalpy(Vec solution){
     3778
     3779        const int    numdof=NDOF1*NUMVERTICES;
     3780
     3781        int          i;
     3782        int*         doflist=NULL;
     3783        double       values[numdof];
     3784        double       enthalpy;
     3785        GaussPenta   *gauss=NULL;
     3786
     3787        /*Get dof list: */
     3788        GetDofList(&doflist,NoneApproximationEnum,GsetEnum);
     3789        Input* h_input=inputs->GetInput(EnthalpyEnum); _assert_(h_input);
     3790
     3791        gauss=new GaussPenta();
     3792        for(i=0;i<NUMVERTICES;i++){
     3793                /*Recover temperature*/
     3794                gauss->GaussVertex(i);
     3795                h_input->GetParameterValue(&enthalpy,gauss);
     3796                values[i]=enthalpy;
     3797        }
     3798
     3799        /*Add value to global vector*/
     3800        VecSetValues(solution,numdof,doflist,(const double*)values,INSERT_VALUES);
     3801
     3802        /*Free ressources:*/
     3803        delete gauss;
     3804        xfree((void**)&doflist);
     3805}
     3806/*}}}*/
     3807/*FUNCTION Penta::InputUpdateFromSolutionThermal {{{1*/
     3808void  Penta::InputUpdateFromSolutionThermal(double* solution){
     3809
     3810        const int    numdof=NDOF1*NUMVERTICES;
     3811
     3812        bool   converged;
     3813        int    i,rheology_law;
     3814        double xyz_list[NUMVERTICES][3];
     3815        double values[numdof];
     3816        double B[numdof];
     3817        double B_average,s_average;
     3818        int*   doflist=NULL;
     3819
     3820        /*Get dof list: */
     3821        GetDofList(&doflist,NoneApproximationEnum,GsetEnum);
     3822
     3823        /*Use the dof list to index into the solution vector: */
     3824        for(i=0;i<numdof;i++){
     3825                values[i]=solution[doflist[i]];
     3826
     3827                /*Check solution*/
     3828                if(isnan(values[i])) _error_("NaN found in solution vector");
     3829                //if(values[i]<0)      printf("temperature < 0°K found in solution vector\n");
     3830                //if(values[i]>275)    printf("temperature > 275°K found in solution vector (Paterson's rheology associated is negative)\n");
     3831        }
     3832
     3833        /*Get all inputs and parameters*/
     3834        GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
     3835        Input* surface_input=inputs->GetInput(SurfaceEnum); _assert_(surface_input);
     3836
     3837        this->inputs->GetParameterValue(&converged,ConvergedEnum);
     3838        if(converged){
     3839                this->inputs->AddInput(new PentaVertexInput(TemperatureEnum,values));
     3840
     3841                /*Update Rheology only if converged (we must make sure that the temperature is below melting point
     3842                 * otherwise the rheology could be negative*/
     3843                this->parameters->FindParam(&rheology_law,MaterialsRheologyLawEnum);
     3844                switch(rheology_law){
     3845                        case NoneEnum:
     3846                                /*Do nothing: B is not temperature dependent*/
     3847                                break;
     3848                        case PatersonEnum:
     3849                                B_average=Paterson((values[0]+values[1]+values[2]+values[3]+values[4]+values[5])/6.0);
     3850                                for(i=0;i<numdof;i++) B[i]=B_average;
     3851                                this->matice->inputs->AddInput(new PentaVertexInput(MaterialsRheologyBEnum,B));
     3852                                break;
     3853                        case ArrheniusEnum:
     3854                                surface_input->GetParameterAverage(&s_average);
     3855                                B_average=Arrhenius((values[0]+values[1]+values[2]+values[3]+values[4]+values[5])/6.0,
     3856                                                        s_average-((xyz_list[0][2]+xyz_list[1][2]+xyz_list[2][2]+xyz_list[3][2]+xyz_list[4][2]+xyz_list[5][2])/6.0),
     3857                                                        matice->GetN());
     3858                                for(i=0;i<numdof;i++) B[i]=B_average;
     3859                                this->matice->inputs->AddInput(new PentaVertexInput(MaterialsRheologyBEnum,B));
     3860                                break;
     3861                        default:
     3862                                _error_("Rheology law %s not supported yet",EnumToStringx(rheology_law));
     3863
     3864                }
     3865        }
     3866        else{
     3867                this->inputs->AddInput(new PentaVertexInput(TemperaturePicardEnum,values));
     3868        }
     3869
     3870        /*Free ressources:*/
     3871        xfree((void**)&doflist);
     3872}
     3873/*}}}*/
     3874/*FUNCTION Penta::InputUpdateFromSolutionEnthalpy {{{1*/
     3875void  Penta::InputUpdateFromSolutionEnthalpy(double* solution){
     3876
     3877        const int    numdof=NDOF1*NUMVERTICES;
     3878
     3879        bool   converged;
     3880        int    i,rheology_law;
     3881        double xyz_list[NUMVERTICES][3];
     3882        double values[numdof];
     3883        double pressure[NUMVERTICES];
     3884        double temperatures[numdof];
     3885        double waterfraction[numdof];
     3886        double B[numdof];
     3887        double B_average,s_average;
     3888        int*   doflist=NULL;
     3889
     3890        /*Get dof list: */
     3891        GetDofList(&doflist,NoneApproximationEnum,GsetEnum);
     3892
     3893        /*Use the dof list to index into the solution vector: */
     3894        for(i=0;i<numdof;i++){
     3895                values[i]=solution[doflist[i]];
     3896
     3897                /*Check solution*/
     3898                if(isnan(values[i])) _error_("NaN found in solution vector");
     3899        }
     3900
     3901        /*Get all inputs and parameters*/
     3902        GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
     3903        GetParameterListOnVertices(&pressure[0],PressureEnum);
     3904        Input* surface_input=inputs->GetInput(SurfaceEnum); _assert_(surface_input);
     3905       
     3906
     3907//      this->inputs->GetParameterValue(&converged,ConvergedEnum);
     3908//      if(converged){
     3909                /*Convert enthalpy into temperature and water fraction*/
     3910                for(i=0;i<numdof;i++) matpar->EnthalpyToThermal(&temperatures[i],&waterfraction[i],values[i],pressure[i]);
     3911                       
     3912                this->inputs->AddInput(new PentaVertexInput(EnthalpyEnum,values));
     3913                this->inputs->AddInput(new PentaVertexInput(WaterfractionEnum,waterfraction));
     3914                this->inputs->AddInput(new PentaVertexInput(TemperatureEnum,temperatures));
     3915
     3916                /*Update Rheology only if converged (we must make sure that the temperature is below melting point
     3917                 * otherwise the rheology could be negative*/
     3918                this->parameters->FindParam(&rheology_law,MaterialsRheologyLawEnum);
     3919                switch(rheology_law){
     3920                        case NoneEnum:
     3921                                /*Do nothing: B is not temperature dependent*/
     3922                                break;
     3923                        case PatersonEnum:
     3924                                B_average=Paterson((temperatures[0]+temperatures[1]+temperatures[2]+temperatures[3]+temperatures[4]+temperatures[5])/6.0);
     3925                                for(i=0;i<numdof;i++) B[i]=B_average;
     3926                                this->matice->inputs->AddInput(new PentaVertexInput(MaterialsRheologyBEnum,B));
     3927                                break;
     3928                        case ArrheniusEnum:
     3929                                surface_input->GetParameterAverage(&s_average);
     3930                                B_average=Arrhenius((temperatures[0]+temperatures[1]+temperatures[2]+temperatures[3]+temperatures[4]+temperatures[5])/6.0,
     3931                                                        s_average-((xyz_list[0][2]+xyz_list[1][2]+xyz_list[2][2]+xyz_list[3][2]+xyz_list[4][2]+xyz_list[5][2])/6.0),
     3932                                                        matice->GetN());
     3933                                for(i=0;i<numdof;i++) B[i]=B_average;
     3934                                this->matice->inputs->AddInput(new PentaVertexInput(MaterialsRheologyBEnum,B));
     3935                                break;
     3936                        default:
     3937                                _error_("Rheology law %s not supported yet",EnumToStringx(rheology_law));
     3938
     3939                }
     3940//      }
     3941//      else{
     3942//              this->inputs->AddInput(new PentaVertexInput(EnthalpyPicardEnum,values));
     3943//      }
     3944
     3945        /*Free ressources:*/
     3946        xfree((void**)&doflist);
     3947}
     3948/*}}}*/
     3949#endif
     3950
     3951#ifdef _HAVE_CONTROL_
     3952/*FUNCTION Penta::ControlInputGetGradient{{{1*/
     3953void Penta::ControlInputGetGradient(Vec gradient,int enum_type){
     3954
     3955        int doflist1[NUMVERTICES];
     3956        Input* input=NULL;
     3957
     3958        if(enum_type==MaterialsRheologyBbarEnum){
     3959                if(!IsOnBed()) return;
     3960                input=(Input*)matice->inputs->GetInput(MaterialsRheologyBEnum);
     3961        }
     3962        else{
     3963                input=inputs->GetInput(enum_type);
     3964        }
     3965        if (!input) _error_("Input %s not found",EnumToStringx(enum_type));
     3966        if (input->Enum()!=ControlInputEnum) _error_("Input %s is not a ControlInput",EnumToStringx(enum_type));
     3967
     3968        this->GetDofList1(&doflist1[0]);
     3969        ((ControlInput*)input)->GetGradient(gradient,&doflist1[0]);
     3970
     3971}/*}}}*/
     3972/*FUNCTION Penta::ControlInputScaleGradient{{{1*/
     3973void Penta::ControlInputScaleGradient(int enum_type,double scale){
     3974
     3975        Input* input=NULL;
     3976
     3977        if(enum_type==MaterialsRheologyBbarEnum){
     3978                input=(Input*)matice->inputs->GetInput(MaterialsRheologyBEnum);
     3979        }
     3980        else{
     3981                input=inputs->GetInput(enum_type);
     3982        }
     3983        if (!input) _error_("Input %s not found",EnumToStringx(enum_type));
     3984        if (input->Enum()!=ControlInputEnum) _error_("Input %s is not a ControlInput",EnumToStringx(enum_type));
     3985
     3986        ((ControlInput*)input)->ScaleGradient(scale);
     3987}/*}}}*/
     3988/*FUNCTION Penta::ControlInputSetGradient{{{1*/
     3989void Penta::ControlInputSetGradient(double* gradient,int enum_type){
     3990
     3991        int    doflist1[NUMVERTICES];
     3992        double grad_list[NUMVERTICES];
     3993        Input* grad_input=NULL;
     3994        Input* input=NULL;
     3995
     3996        if(enum_type==MaterialsRheologyBbarEnum){
     3997                input=(Input*)matice->inputs->GetInput(MaterialsRheologyBEnum);
     3998        }
     3999        else{
     4000                input=inputs->GetInput(enum_type);
     4001        }
     4002        if (!input) _error_("Input %s not found",EnumToStringx(enum_type));
     4003        if (input->Enum()!=ControlInputEnum) _error_("Input %s is not a ControlInput",EnumToStringx(enum_type));
     4004
     4005        this->GetDofList1(&doflist1[0]);
     4006        for(int i=0;i<NUMVERTICES;i++) grad_list[i]=gradient[doflist1[i]];
     4007        grad_input=new PentaVertexInput(GradientEnum,grad_list);
     4008        ((ControlInput*)input)->SetGradient(grad_input);
     4009
     4010}/*}}}*/
     4011/*FUNCTION Penta::CreatePVectorAdjointHoriz{{{1*/
     4012ElementVector* Penta::CreatePVectorAdjointHoriz(void){
     4013
     4014        int approximation;
     4015        inputs->GetParameterValue(&approximation,ApproximationEnum);
     4016
     4017        switch(approximation){
     4018                case MacAyealApproximationEnum:
     4019                        return CreatePVectorAdjointMacAyeal();
     4020                case PattynApproximationEnum:
     4021                        return CreatePVectorAdjointPattyn();
     4022                case NoneApproximationEnum:
     4023                        return NULL;
     4024                case StokesApproximationEnum:
     4025                        return CreatePVectorAdjointStokes();
     4026                default:
     4027                        _error_("Approximation %s not supported yet",EnumToStringx(approximation));
     4028        }
     4029}
     4030/*}}}*/
     4031/*FUNCTION Penta::CreatePVectorAdjointMacAyeal{{{1*/
     4032ElementVector* Penta::CreatePVectorAdjointMacAyeal(){
     4033
     4034        if (!IsOnBed()) return NULL;
     4035
     4036        /*Call Tria function*/
     4037        Tria* tria=(Tria*)SpawnTria(0,1,2); //nodes 0, 1 and 2 make the new tria.
     4038        ElementVector* pe=tria->CreatePVectorAdjointHoriz();
     4039        delete tria->matice; delete tria;
     4040
     4041        /*clean up and return*/
     4042        return pe;
     4043}
     4044/*}}}*/
     4045/*FUNCTION Penta::CreatePVectorAdjointPattyn{{{1*/
     4046ElementVector* Penta::CreatePVectorAdjointPattyn(void){
     4047
     4048        if (!IsOnSurface()) return NULL;
     4049
     4050        /*Call Tria function*/
     4051        Tria* tria=(Tria*)SpawnTria(3,4,5); //nodes 3, 4 and 5 make the new tria (upper face).
     4052        ElementVector* pe=tria->CreatePVectorAdjointHoriz();
     4053        delete tria->matice; delete tria;
     4054
     4055        /*clean up and return*/
     4056        return pe;
     4057}
     4058/*}}}*/
     4059/*FUNCTION Penta::CreatePVectorAdjointStokes{{{1*/
     4060ElementVector* Penta::CreatePVectorAdjointStokes(void){
     4061
     4062        if (!IsOnSurface()) return NULL;
     4063
     4064        /*Call Tria function*/
     4065        Tria* tria=(Tria*)SpawnTria(3,4,5); //nodes 3, 4 and 5 make the new tria (upper face).
     4066        ElementVector* pe=tria->CreatePVectorAdjointStokes();
     4067        delete tria->matice; delete tria;
     4068
     4069        /*clean up and return*/
     4070        return pe;
     4071}
     4072/*}}}*/
     4073/*FUNCTION Penta::Gradj {{{1*/
     4074void  Penta::Gradj(Vec gradient,int control_type){
     4075        /*dJ/dalpha = ∂L/∂alpha = ∂J/∂alpha + ∂/∂alpha(KU-F)*/
     4076
     4077        int              i,approximation;
     4078        Tria*            tria=NULL;
     4079
     4080        /*If on water, skip grad (=0): */
     4081        if(IsOnWater())return;
     4082
     4083        /*First deal with ∂/∂alpha(KU-F)*/
     4084        switch(control_type){
     4085
     4086                case FrictionCoefficientEnum:
     4087                        inputs->GetParameterValue(&approximation,ApproximationEnum);
     4088                        switch(approximation){
     4089                                case MacAyealApproximationEnum:
     4090                                        GradjDragMacAyeal(gradient);
     4091                                        break;
     4092                                case PattynApproximationEnum:
     4093                                        GradjDragPattyn(gradient);
     4094                                        break;
     4095                                case StokesApproximationEnum:
     4096                                        GradjDragStokes(gradient);
     4097                                        break;
     4098                                case NoneApproximationEnum:
     4099                                        /*Gradient is 0*/
     4100                                        break;
     4101                                default:
     4102                                        _error_("approximation %s not supported yet",EnumToStringx(approximation));
     4103                        }
     4104                        break;
     4105
     4106                case MaterialsRheologyBbarEnum:
     4107                        inputs->GetParameterValue(&approximation,ApproximationEnum);
     4108                        switch(approximation){
     4109                                case MacAyealApproximationEnum:
     4110                                        GradjBbarMacAyeal(gradient);
     4111                                        break;
     4112                                case PattynApproximationEnum:
     4113                                        GradjBbarPattyn(gradient);
     4114                                        break;
     4115                                case StokesApproximationEnum:
     4116                                        GradjBbarStokes(gradient);
     4117                                        break;
     4118                                case NoneApproximationEnum:
     4119                                        /*Gradient is 0*/
     4120                                        break;
     4121                                default:
     4122                                        _error_("approximation %s not supported yet",EnumToStringx(approximation));
     4123                        }
     4124                        break;
     4125
     4126                default:
     4127                        _error_("control type %s not supported yet: ",EnumToStringx(control_type));
     4128        }
     4129
     4130        /*Now deal with ∂J/∂alpha*/
     4131        int        *responses = NULL;
     4132        int         num_responses,resp;
     4133        this->parameters->FindParam(&num_responses,InversionNumCostFunctionsEnum);
     4134        this->parameters->FindParam(&responses,NULL,NULL,StepResponsesEnum);
     4135
     4136        for(resp=0;resp<num_responses;resp++) switch(responses[resp]){
     4137
     4138                case ThicknessAbsMisfitEnum:
     4139                case SurfaceAbsVelMisfitEnum:
     4140                case SurfaceRelVelMisfitEnum:
     4141                case SurfaceLogVelMisfitEnum:
     4142                case SurfaceLogVxVyMisfitEnum:
     4143                case SurfaceAverageVelMisfitEnum:
     4144                        /*Nothing, J does not depends on the parameter being inverted for*/
     4145                        break;
     4146                case DragCoefficientAbsGradientEnum:
     4147                        if (!IsOnBed()) return;
     4148                        tria=(Tria*)SpawnTria(0,1,2); //nodes 0, 1 and 2 make the new tria.
     4149                        tria->GradjDragGradient(gradient,resp);
     4150                        delete tria->matice; delete tria;
     4151                        break;
     4152                case RheologyBbarAbsGradientEnum:
     4153                        if (!IsOnBed()) return;
     4154                        tria=(Tria*)SpawnTria(0,1,2); //nodes 0, 1 and 2 make the new tria.
     4155                        tria->GradjBGradient(gradient,resp);
     4156                        delete tria->matice; delete tria;
     4157                        break;
     4158                default:
     4159                        _error_("response %s not supported yet",EnumToStringx(responses[resp]));
     4160        }
     4161        xfree((void**)&responses);
     4162}
     4163/*}}}*/
     4164/*FUNCTION Penta::GradjDragMacAyeal {{{1*/
     4165void  Penta::GradjDragMacAyeal(Vec gradient){
     4166
     4167        /*Gradient is 0 if on shelf or not on bed*/
     4168        if(IsOnShelf() || !IsOnBed()) return;
     4169
     4170        /*Spawn tria*/
     4171        Tria* tria=(Tria*)SpawnTria(0,1,2); //nodes 0, 1 and 2 make the new tria.
     4172        tria->GradjDragMacAyeal(gradient);
     4173        delete tria->matice; delete tria;
     4174
     4175} /*}}}*/
     4176/*FUNCTION Penta::GradjDragPattyn {{{1*/
     4177void  Penta::GradjDragPattyn(Vec gradient){
     4178
     4179        int        i,j,ig;
     4180        int        analysis_type;
     4181        int        doflist1[NUMVERTICES];
     4182        double     vx,vy,lambda,mu,alpha_complement,Jdet;
     4183        double     bed,thickness,Neff,drag;
     4184        double     xyz_list[NUMVERTICES][3];
     4185        double     xyz_list_tria[NUMVERTICES2D][3]={0.0};
     4186        double     dk[NDOF3];
     4187        double     grade_g[NUMVERTICES]={0.0};
     4188        double     grade_g_gaussian[NUMVERTICES];
     4189        double     basis[6];
     4190        Friction*  friction=NULL;
     4191        GaussPenta  *gauss=NULL;
     4192
     4193        /*Gradient is 0 if on shelf or not on bed*/
     4194        if(IsOnShelf() || !IsOnBed()) return;
     4195
     4196        /*Retrieve all inputs and parameters*/
     4197        parameters->FindParam(&analysis_type,AnalysisTypeEnum);
     4198        GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
     4199        for(i=0;i<NUMVERTICES2D;i++) for(j=0;j<2;j++) xyz_list_tria[i][j]=xyz_list[i][j];
     4200        GetDofList1(&doflist1[0]);
     4201        Input* adjointx_input=inputs->GetInput(AdjointxEnum);               _assert_(adjointx_input);
     4202        Input* adjointy_input=inputs->GetInput(AdjointyEnum);               _assert_(adjointy_input);
     4203        Input* vx_input=inputs->GetInput(VxEnum);                           _assert_(vx_input);
     4204        Input* vy_input=inputs->GetInput(VyEnum);                           _assert_(vy_input);
     4205        Input* dragcoefficient_input=inputs->GetInput(FrictionCoefficientEnum); _assert_(dragcoefficient_input);
     4206
     4207        /*Build frictoin element, needed later: */
     4208        friction=new Friction("2d",inputs,matpar,analysis_type);
     4209
     4210        /* Start  looping on the number of gaussian points: */
     4211        gauss=new GaussPenta(0,1,2,4);
     4212        for (ig=gauss->begin();ig<gauss->end();ig++){
     4213
     4214                gauss->GaussPoint(ig);
     4215
     4216                GetTriaJacobianDeterminant(&Jdet, &xyz_list_tria[0][0],gauss);
     4217                GetNodalFunctionsP1(basis, gauss);
     4218
     4219                /*Build alpha_complement_list: */
     4220                friction->GetAlphaComplement(&alpha_complement, gauss,VxEnum,VyEnum,VzEnum);
     4221
     4222                dragcoefficient_input->GetParameterValue(&drag, gauss);
     4223                adjointx_input->GetParameterValue(&lambda, gauss);
     4224                adjointy_input->GetParameterValue(&mu, gauss);
     4225                vx_input->GetParameterValue(&vx,gauss);
     4226                vy_input->GetParameterValue(&vy,gauss);
     4227                dragcoefficient_input->GetParameterDerivativeValue(&dk[0],&xyz_list[0][0],gauss);
     4228
     4229                /*Build gradje_g_gaussian vector (actually -dJ/ddrag): */
     4230                for (i=0;i<NUMVERTICES;i++){
     4231                        grade_g_gaussian[i]=-2*drag*alpha_complement*((lambda*vx+mu*vy))*Jdet*gauss->weight*basis[i]; /*basis are 0 for the 3 upper nodes*/
     4232                }
     4233
     4234                /*Add gradje_g_gaussian vector to gradje_g: */
     4235                for(i=0;i<NUMVERTICES;i++){
     4236                        _assert_(!isnan(grade_g[i]));
     4237                        grade_g[i]+=grade_g_gaussian[i];
     4238                }
     4239        }
     4240        VecSetValues(gradient,NUMVERTICES,doflist1,(const double*)grade_g,ADD_VALUES);
     4241
     4242        /*Clean up and return*/
     4243        delete gauss;
     4244        delete friction;
     4245}
     4246/*}}}*/
     4247/*FUNCTION Penta::GradjDragStokes {{{1*/
     4248void  Penta::GradjDragStokes(Vec gradient){
     4249
     4250        int        i,j,ig;
     4251        int        analysis_type;
     4252        int        doflist1[NUMVERTICES];
     4253        double     bed,thickness,Neff;
     4254        double     lambda,mu,xi,Jdet,vx,vy,vz;
     4255        double     alpha_complement,drag;
     4256        double     surface_normal[3],bed_normal[3];
     4257        double     xyz_list[NUMVERTICES][3];
     4258        double     xyz_list_tria[NUMVERTICES2D][3]={0.0};
     4259        double     dk[NDOF3];
     4260        double     basis[6];
     4261        double     grade_g[NUMVERTICES]={0.0};
     4262        double     grade_g_gaussian[NUMVERTICES];
     4263        Friction*  friction=NULL;
     4264        GaussPenta* gauss=NULL;
     4265
     4266        /*Gradient is 0 if on shelf or not on bed*/
     4267        if(IsOnShelf() || !IsOnBed()) return;
     4268
     4269        /*Retrieve all inputs and parameters*/
     4270        parameters->FindParam(&analysis_type,AnalysisTypeEnum);
     4271        GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
     4272        for(i=0;i<NUMVERTICES2D;i++) for(j=0;j<2;j++) xyz_list_tria[i][j]=xyz_list[i][j];
     4273        GetDofList1(&doflist1[0]);
     4274        Input* drag_input    =inputs->GetInput(FrictionCoefficientEnum); _assert_(drag_input);
     4275        Input* vx_input      =inputs->GetInput(VxEnum);              _assert_(vx_input);
     4276        Input* vy_input      =inputs->GetInput(VyEnum);              _assert_(vy_input);
     4277        Input* vz_input      =inputs->GetInput(VzEnum);              _assert_(vz_input);
     4278        Input* adjointx_input=inputs->GetInput(AdjointxEnum);        _assert_(adjointx_input);
     4279        Input* adjointy_input=inputs->GetInput(AdjointyEnum);        _assert_(adjointy_input);
     4280        Input* adjointz_input=inputs->GetInput(AdjointzEnum);        _assert_(adjointz_input);
     4281
     4282        /*Build frictoin element, needed later: */
     4283        friction=new Friction("3d",inputs,matpar,analysis_type);
     4284
     4285        /* Start  looping on the number of gaussian points: */
     4286        gauss=new GaussPenta(0,1,2,4);
     4287        for(ig=gauss->begin();ig<gauss->end();ig++){
     4288
     4289                gauss->GaussPoint(ig);
     4290
     4291                /*Recover alpha_complement and drag: */
     4292                friction->GetAlphaComplement(&alpha_complement, gauss,VxEnum,VyEnum,VzEnum);
     4293                drag_input->GetParameterValue(&drag,gauss);
     4294
     4295                /*recover lambda mu and xi: */
     4296                adjointx_input->GetParameterValue(&lambda,gauss);
     4297                adjointy_input->GetParameterValue(&mu    ,gauss);
     4298                adjointz_input->GetParameterValue(&xi    ,gauss);
     4299
     4300                /*recover vx vy and vz: */
     4301                vx_input->GetParameterValue(&vx, gauss);
     4302                vy_input->GetParameterValue(&vy, gauss);
     4303                vz_input->GetParameterValue(&vz, gauss);
     4304
     4305                /*Get normal vector to the bed */
     4306                SurfaceNormal(&surface_normal[0],xyz_list_tria);
     4307
     4308                bed_normal[0]=-surface_normal[0]; //Function is for upper surface, so the normal to the bed is the opposite of the result
     4309                bed_normal[1]=-surface_normal[1];
     4310                bed_normal[2]=-surface_normal[2];
     4311
     4312                /* Get Jacobian determinant: */
     4313                GetTriaJacobianDeterminant(&Jdet,&xyz_list_tria[0][0],gauss);
     4314                GetNodalFunctionsP1(basis, gauss);
     4315
     4316                /*Get k derivative: dk/dx */
     4317                drag_input->GetParameterDerivativeValue(&dk[0],&xyz_list[0][0],gauss);
     4318
     4319                /*Build gradje_g_gaussian vector (actually -dJ/ddrag): */
     4320                for (i=0;i<NUMVERTICES;i++){
     4321                        //standard gradient dJ/dki
     4322                        grade_g_gaussian[i]=(
     4323                                                -lambda*(2*drag*alpha_complement*(vx - vz*bed_normal[0]*bed_normal[2]))
     4324                                                -mu    *(2*drag*alpha_complement*(vy - vz*bed_normal[1]*bed_normal[2]))
     4325                                                -xi    *(2*drag*alpha_complement*(-vx*bed_normal[0]*bed_normal[2]-vy*bed_normal[1]*bed_normal[2]))
     4326                                                )*Jdet*gauss->weight*basis[i];
     4327                }
     4328
     4329                /*Add gradje_g_gaussian vector to gradje_g: */
     4330                for( i=0; i<NUMVERTICES; i++)grade_g[i]+=grade_g_gaussian[i];
     4331        }
     4332
     4333        VecSetValues(gradient,NUMVERTICES,doflist1,(const double*)grade_g,ADD_VALUES);
     4334
     4335        delete friction;
     4336        delete gauss;
     4337}
     4338/*}}}*/
     4339/*FUNCTION Penta::GradjBbarMacAyeal {{{1*/
     4340void  Penta::GradjBbarMacAyeal(Vec gradient){
     4341
     4342        /*This element should be collapsed into a tria element at its base*/
     4343        if (!IsOnBed()) return;
     4344
     4345        /*Depth Average B*/
     4346        this->InputDepthAverageAtBase(MaterialsRheologyBEnum,MaterialsRheologyBbarEnum,MaterialsEnum);
     4347
     4348        /*Collapse element to the base*/
     4349        Tria* tria=(Tria*)SpawnTria(0,1,2); //nodes 0, 1 and 2 make the new tria (lower face).
     4350        tria->GradjBMacAyeal(gradient);
     4351        delete tria->matice; delete tria;
     4352
     4353        /*delete Average B*/
     4354        this->matice->inputs->DeleteInput(MaterialsRheologyBbarEnum);
     4355
     4356} /*}}}*/
     4357/*FUNCTION Penta::GradjBbarPattyn {{{1*/
     4358void  Penta::GradjBbarPattyn(Vec gradient){
     4359
     4360        /*Gradient is computed on bed only (Bbar)*/
     4361        if (!IsOnBed()) return;
     4362
     4363        /*Depth Average B*/
     4364        this->InputDepthAverageAtBase(MaterialsRheologyBEnum,MaterialsRheologyBbarEnum,MaterialsEnum);
     4365
     4366        /*Collapse element to the base*/
     4367        Tria* tria=(Tria*)SpawnTria(0,1,2);
     4368        tria->GradjBMacAyeal(gradient);    //We use MacAyeal as an estimate for now
     4369        delete tria->matice; delete tria;
     4370
     4371        /*delete Average B*/
     4372        this->matice->inputs->DeleteInput(MaterialsRheologyBbarEnum);
     4373} /*}}}*/
     4374/*FUNCTION Penta::GradjBbarStokes {{{1*/
     4375void  Penta::GradjBbarStokes(Vec gradient){
     4376
     4377        /*Gradient is computed on bed only (Bbar)*/
     4378        if (!IsOnBed()) return;
     4379
     4380        /*Depth Average B*/
     4381        this->InputDepthAverageAtBase(MaterialsRheologyBEnum,MaterialsRheologyBbarEnum,MaterialsEnum);
     4382
     4383        /*Collapse element to the base*/
     4384        Tria* tria=(Tria*)SpawnTria(0,1,2);
     4385        tria->GradjBMacAyeal(gradient);    //We use MacAyeal as an estimate for now
     4386        delete tria->matice; delete tria;
     4387
     4388        /*delete Average B*/
     4389        this->matice->inputs->DeleteInput(MaterialsRheologyBbarEnum);
     4390} /*}}}*/
     4391/*FUNCTION Penta::InputControlUpdate{{{1*/
     4392void  Penta::InputControlUpdate(double scalar,bool save_parameter){
     4393
     4394        /*Intermediary*/
     4395        int    num_controls;
     4396        int*   control_type=NULL;
     4397        Input* input=NULL;
     4398
     4399        /*retrieve some parameters: */
     4400        this->parameters->FindParam(&num_controls,InversionNumControlParametersEnum);
     4401        this->parameters->FindParam(&control_type,NULL,InversionControlParametersEnum);
     4402
     4403        for(int i=0;i<num_controls;i++){
     4404
     4405                if(control_type[i]==MaterialsRheologyBbarEnum){
     4406                        if (!IsOnBed()) goto cleanup_and_return;
     4407                        input=(Input*)matice->inputs->GetInput(MaterialsRheologyBEnum); _assert_(input);
     4408                }
     4409                else{
     4410                        input=(Input*)this->inputs->GetInput(control_type[i]); _assert_(input);
     4411                }
     4412
     4413                if (input->Enum()!=ControlInputEnum) _error_("input %s is not a ControlInput",EnumToStringx(control_type[i]));
     4414
     4415                ((ControlInput*)input)->UpdateValue(scalar);
     4416                ((ControlInput*)input)->Constrain();
     4417                if (save_parameter) ((ControlInput*)input)->SaveValue();
     4418
     4419                if(control_type[i]==MaterialsRheologyBbarEnum){
     4420                        this->InputExtrude(MaterialsRheologyBEnum,MaterialsEnum);
     4421                }
     4422        }
     4423
     4424        /*Clean up and return*/
     4425cleanup_and_return:
     4426        xfree((void**)&control_type);
     4427}
     4428/*}}}*/
     4429/*FUNCTION Penta::InputUpdateFromSolutionAdjointStokes {{{1*/
     4430void  Penta::InputUpdateFromSolutionAdjointStokes(double* solution){
     4431
     4432        const int    numdof=NDOF4*NUMVERTICES;
     4433
     4434        int    i;
     4435        double values[numdof];
     4436        double lambdax[NUMVERTICES];
     4437        double lambday[NUMVERTICES];
     4438        double lambdaz[NUMVERTICES];
     4439        double lambdap[NUMVERTICES];
     4440        int*   doflist=NULL;
     4441
     4442        /*Get dof list: */
     4443        GetDofList(&doflist,NoneApproximationEnum,GsetEnum);
     4444
     4445        /*Use the dof list to index into the solution vector: */
     4446        for(i=0;i<numdof;i++) values[i]=solution[doflist[i]];
     4447
     4448        /*Ok, we have vx and vy in values, fill in vx and vy arrays: */
     4449        for(i=0;i<NUMVERTICES;i++){
     4450                lambdax[i]=values[i*NDOF4+0];
     4451                lambday[i]=values[i*NDOF4+1];
     4452                lambdaz[i]=values[i*NDOF4+2];
     4453                lambdap[i]=values[i*NDOF4+3];
     4454
     4455                /*Check solution*/
     4456                if(isnan(lambdax[i])) _error_("NaN found in solution vector");
     4457                if(isnan(lambday[i])) _error_("NaN found in solution vector");
     4458                if(isnan(lambdaz[i])) _error_("NaN found in solution vector");
     4459                if(isnan(lambdap[i])) _error_("NaN found in solution vector");
     4460        }
     4461
     4462        /*Add vx and vy as inputs to the tria element: */
     4463        this->inputs->AddInput(new PentaVertexInput(AdjointxEnum,lambdax));
     4464        this->inputs->AddInput(new PentaVertexInput(AdjointyEnum,lambday));
     4465        this->inputs->AddInput(new PentaVertexInput(AdjointzEnum,lambdaz));
     4466        this->inputs->AddInput(new PentaVertexInput(AdjointpEnum,lambdap));
     4467
     4468        /*Free ressources:*/
     4469        xfree((void**)&doflist);
     4470}
     4471/*}}}*/
     4472/*FUNCTION Penta::InputUpdateFromSolutionAdjointHoriz {{{1*/
     4473void  Penta::InputUpdateFromSolutionAdjointHoriz(double* solution){
     4474
     4475        const int numdof=NDOF2*NUMVERTICES;
     4476
     4477        int    i;
     4478        double values[numdof];
     4479        double lambdax[NUMVERTICES];
     4480        double lambday[NUMVERTICES];
     4481        int*   doflist=NULL;
     4482
     4483        /*Get dof list: */
     4484        GetDofList(&doflist,NoneApproximationEnum,GsetEnum);
     4485
     4486        /*Use the dof list to index into the solution vector: */
     4487        for(i=0;i<numdof;i++) values[i]=solution[doflist[i]];
     4488
     4489        /*Ok, we have vx and vy in values, fill in vx and vy arrays: */
     4490        for(i=0;i<NUMVERTICES;i++){
     4491                lambdax[i]=values[i*NDOF2+0];
     4492                lambday[i]=values[i*NDOF2+1];
     4493
     4494                /*Check solution*/
     4495                if(isnan(lambdax[i]))       _error_("NaN found in solution vector");
     4496                if(isnan(lambday[i]))       _error_("NaN found in solution vector");
     4497        }
     4498
     4499        /*Add vx and vy as inputs to the tria element: */
     4500        this->inputs->AddInput(new PentaVertexInput(AdjointxEnum,lambdax));
     4501        this->inputs->AddInput(new PentaVertexInput(AdjointyEnum,lambday));
     4502
     4503        /*Free ressources:*/
     4504        xfree((void**)&doflist);
     4505}
     4506/*}}}*/
     4507/*FUNCTION Penta::SurfaceAverageVelMisfit {{{1*/
     4508double Penta::SurfaceAverageVelMisfit(bool process_units,int weight_index){
     4509
     4510        int    approximation;
     4511        double J;
     4512        Tria*  tria=NULL;
     4513
     4514        /*retrieve inputs :*/
     4515        inputs->GetParameterValue(&approximation,ApproximationEnum);
     4516
     4517        /*If on water, return 0: */
     4518        if(IsOnWater())return 0;
     4519
     4520        /*Bail out if this element if:
     4521         * -> Non MacAyeal and not on the surface
     4522         * -> MacAyeal (2d model) and not on bed) */
     4523        if ((approximation!=MacAyealApproximationEnum && !IsOnSurface()) || (approximation==MacAyealApproximationEnum && !IsOnBed())){
     4524                return 0;
     4525        }
     4526        else if (approximation==MacAyealApproximationEnum){
     4527
     4528                /*This element should be collapsed into a tria element at its base. Create this tria element,
     4529                 * and compute SurfaceAverageVelMisfit*/
     4530                tria=(Tria*)SpawnTria(0,1,2); //nodes 0, 1 and 2 make the new tria (lower face).
     4531                J=tria->SurfaceAverageVelMisfit(process_units,weight_index);
     4532                delete tria->matice; delete tria;
     4533                return J;
     4534        }
     4535        else{
     4536
     4537                tria=(Tria*)SpawnTria(3,4,5); //nodes 3, 4 and 5 make the new tria (upper face).
     4538                J=tria->SurfaceAverageVelMisfit(process_units,weight_index);
     4539                delete tria->matice; delete tria;
     4540                return J;
     4541        }
     4542}
     4543/*}}}*/
     4544/*FUNCTION Penta::SurfaceAbsVelMisfit {{{1*/
     4545double Penta::SurfaceAbsVelMisfit(bool process_units,int weight_index){
     4546
     4547        int    approximation;
     4548        double J;
     4549        Tria*  tria=NULL;
     4550
     4551        /*retrieve inputs :*/
     4552        inputs->GetParameterValue(&approximation,ApproximationEnum);
     4553
     4554        /*If on water, return 0: */
     4555        if(IsOnWater())return 0;
     4556
     4557        /*Bail out if this element if:
     4558         * -> Non MacAyeal and not on the surface
     4559         * -> MacAyeal (2d model) and not on bed) */
     4560        if ((approximation!=MacAyealApproximationEnum && !IsOnSurface()) || (approximation==MacAyealApproximationEnum && !IsOnBed())){
     4561                return 0;
     4562        }
     4563        else if (approximation==MacAyealApproximationEnum){
     4564
     4565                /*This element should be collapsed into a tria element at its base. Create this tria element,
     4566                 * and compute SurfaceAbsVelMisfit*/
     4567                tria=(Tria*)SpawnTria(0,1,2); //nodes 0, 1 and 2 make the new tria (lower face).
     4568                J=tria->SurfaceAbsVelMisfit(process_units,weight_index);
     4569                delete tria->matice; delete tria;
     4570                return J;
     4571        }
     4572        else{
     4573
     4574                tria=(Tria*)SpawnTria(3,4,5); //nodes 3, 4 and 5 make the new tria (upper face).
     4575                J=tria->SurfaceAbsVelMisfit(process_units,weight_index);
     4576                delete tria->matice; delete tria;
     4577                return J;
     4578        }
     4579}
     4580/*}}}*/
     4581/*FUNCTION Penta::SurfaceLogVelMisfit {{{1*/
     4582double Penta::SurfaceLogVelMisfit(bool process_units,int weight_index){
     4583
     4584        int    approximation;
     4585        double J;
     4586        Tria*  tria=NULL;
     4587
     4588        /*retrieve inputs :*/
     4589        inputs->GetParameterValue(&approximation,ApproximationEnum);
     4590
     4591        /*If on water, return 0: */
     4592        if(IsOnWater())return 0;
     4593
     4594        /*Bail out if this element if:
     4595         * -> Non MacAyeal and not on the surface
     4596         * -> MacAyeal (2d model) and not on bed) */
     4597        if ((approximation!=MacAyealApproximationEnum && !IsOnSurface()) || (approximation==MacAyealApproximationEnum && !IsOnBed())){
     4598                return 0;
     4599        }
     4600        else if (approximation==MacAyealApproximationEnum){
     4601
     4602                /*This element should be collapsed into a tria element at its base. Create this tria element,
     4603                 * and compute SurfaceLogVelMisfit*/
     4604                tria=(Tria*)SpawnTria(0,1,2); //nodes 0, 1 and 2 make the new tria (lower face).
     4605                J=tria->SurfaceLogVelMisfit(process_units,weight_index);
     4606                delete tria->matice; delete tria;
     4607                return J;
     4608        }
     4609        else{
     4610
     4611                tria=(Tria*)SpawnTria(3,4,5); //nodes 3, 4 and 5 make the new tria (upper face).
     4612                J=tria->SurfaceLogVelMisfit(process_units,weight_index);
     4613                delete tria->matice; delete tria;
     4614                return J;
     4615        }
     4616}
     4617/*}}}*/
     4618/*FUNCTION Penta::SurfaceLogVxVyMisfit {{{1*/
     4619double Penta::SurfaceLogVxVyMisfit(bool process_units,int weight_index){
     4620
     4621        double J;
     4622        Tria* tria=NULL;
     4623
     4624        /*inputs: */
     4625        int  approximation;
     4626
     4627        /*retrieve inputs :*/
     4628        inputs->GetParameterValue(&approximation,ApproximationEnum);
     4629
     4630        /*If on water, return 0: */
     4631        if(IsOnWater())return 0;
     4632
     4633        /*Bail out if this element if:
     4634         * -> Non MacAyeal and not on the surface
     4635         * -> MacAyeal (2d model) and not on bed) */
     4636        if ((approximation!=MacAyealApproximationEnum && !IsOnSurface()) || (approximation==MacAyealApproximationEnum && !IsOnBed())){
     4637                return 0;
     4638        }
     4639        else if (approximation==MacAyealApproximationEnum){
     4640
     4641                /*This element should be collapsed into a tria element at its base. Create this tria element,
     4642                 * and compute SurfaceLogVxVyMisfit*/
     4643                tria=(Tria*)SpawnTria(0,1,2); //nodes 0, 1 and 2 make the new tria (lower face).
     4644                J=tria->SurfaceLogVxVyMisfit(process_units,weight_index);
     4645                delete tria->matice; delete tria;
     4646                return J;
     4647        }
     4648        else{
     4649
     4650                tria=(Tria*)SpawnTria(3,4,5); //nodes 3, 4 and 5 make the new tria (upper face).
     4651                J=tria->SurfaceLogVxVyMisfit(process_units,weight_index);
     4652                delete tria->matice; delete tria;
     4653                return J;
     4654        }
     4655}
     4656/*}}}*/
     4657/*FUNCTION Penta::SurfaceRelVelMisfit {{{1*/
     4658double Penta::SurfaceRelVelMisfit(bool process_units,int weight_index){
     4659
     4660        int    approximation;
     4661        double J;
     4662        Tria*  tria=NULL;
     4663
     4664        /*retrieve inputs :*/
     4665        inputs->GetParameterValue(&approximation,ApproximationEnum);
     4666
     4667        /*If on water, return 0: */
     4668        if(IsOnWater())return 0;
     4669
     4670        /*Bail out if this element if:
     4671         * -> Non MacAyeal and not on the surface
     4672         * -> MacAyeal (2d model) and not on bed) */
     4673        if ((approximation!=MacAyealApproximationEnum && !IsOnSurface()) || (approximation==MacAyealApproximationEnum && !IsOnBed())){
     4674                return 0;
     4675        }
     4676        else if (approximation==MacAyealApproximationEnum){
     4677
     4678                /*This element should be collapsed into a tria element at its base. Create this tria element,
     4679                 * and compute SurfaceRelVelMisfit*/
     4680                tria=(Tria*)SpawnTria(0,1,2); //nodes 0, 1 and 2 make the new tria (lower face).
     4681                J=tria->SurfaceRelVelMisfit(process_units,weight_index);
     4682                delete tria->matice; delete tria;
     4683                return J;
     4684        }
     4685        else{
     4686
     4687                tria=(Tria*)SpawnTria(3,4,5); //nodes 3, 4 and 5 make the new tria (upper face).
     4688                J=tria->SurfaceRelVelMisfit(process_units,weight_index);
     4689                delete tria->matice; delete tria;
     4690                return J;
     4691        }
     4692}
     4693/*}}}*/
     4694/*FUNCTION Penta::ThicknessAbsGradient{{{1*/
     4695double Penta::ThicknessAbsGradient(bool process_units,int weight_index){
     4696
     4697        _error_("Not implemented yet");
     4698}
     4699/*}}}*/
     4700/*FUNCTION Penta::ThicknessAbsMisfit {{{1*/
     4701double Penta::ThicknessAbsMisfit(bool process_units,int weight_index){
     4702
     4703        int    approximation;
     4704        double J;
     4705        Tria*  tria=NULL;
     4706
     4707        /*retrieve inputs :*/
     4708        inputs->GetParameterValue(&approximation,ApproximationEnum);
     4709
     4710        /*If on water, return 0: */
     4711        if(IsOnWater())return 0;
     4712        _error_("Not implemented yet");
     4713
     4714        tria=(Tria*)SpawnTria(0,1,2);
     4715        J=tria->ThicknessAbsMisfit(process_units,weight_index);
     4716        delete tria->matice; delete tria;
     4717        return J;
     4718}
     4719/*}}}*/
     4720/*FUNCTION Penta::DragCoefficientAbsGradient{{{1*/
     4721double Penta::DragCoefficientAbsGradient(bool process_units,int weight_index){
     4722
     4723        double J;
     4724        Tria*  tria=NULL;
     4725
     4726        /*If on water, on shelf or not on bed, skip: */
     4727        if(IsOnWater()|| IsOnShelf() || !IsOnBed()) return 0;
     4728
     4729        tria=(Tria*)SpawnTria(0,1,2); //nodes 0, 1 and 2 make the new tria
     4730        J=tria->DragCoefficientAbsGradient(process_units,weight_index);
     4731        delete tria->matice; delete tria;
     4732        return J;
     4733}
     4734/*}}}*/
     4735/*FUNCTION Penta::RheologyBbarAbsGradient{{{1*/
     4736double Penta::RheologyBbarAbsGradient(bool process_units,int weight_index){
     4737
     4738        double J;
     4739        Tria*  tria=NULL;
     4740
     4741        /*If on water, on shelf or not on bed, skip: */
     4742        if(IsOnWater() || !IsOnBed()) return 0;
     4743
     4744        tria=(Tria*)SpawnTria(0,1,2); //nodes 0, 1 and 2 make the new tria
     4745        J=tria->RheologyBbarAbsGradient(process_units,weight_index);
     4746        delete tria->matice; delete tria;
     4747        return J;
     4748}
     4749/*}}}*/
     4750
     4751#endif
     4752
     4753#ifdef _HAVE_DAKOTA_
     4754/*FUNCTION Penta::InputUpdateFromVectorDakota(double* vector, int name, int type);{{{1*/
     4755void  Penta::InputUpdateFromVectorDakota(double* vector, int name, int type){
     4756       
     4757        int i,j;
     4758
     4759        /*Check that name is an element input*/
     4760        if (!IsInput(name)) return;
     4761
     4762        switch(type){
     4763
     4764                case VertexEnum:
     4765
     4766                        /*New PentaVertexInput*/
     4767                        double values[6];
     4768
     4769                        /*Get values on the 6 vertices*/
     4770                        for (i=0;i<6;i++){
     4771                                values[i]=vector[this->nodes[i]->GetSidList()]; //careful, vector of values here is not parallel distributed, but serial distributed (from a serial Dakota core!)
     4772                        }
     4773
     4774                        /*Branch on the specified type of update: */
     4775                        switch(name){
     4776                                case ThicknessEnum:
     4777                                        /*Update thickness + surface: assume bed is constant. On ice shelves, takes hydrostatic equilibrium {{{2*/
     4778                                        double  thickness[6];
     4779                                        double  thickness_init[6];
     4780                                        double  hydrostatic_ratio[6];
     4781                                        double  surface[6];
     4782                                        double  bed[6];
     4783                                       
     4784                                        /*retrieve inputs: */
     4785                                        GetParameterListOnVertices(&thickness_init[0],ThicknessEnum);
     4786                                        GetParameterListOnVertices(&hydrostatic_ratio[0],GeometryHydrostaticRatioEnum);
     4787                                        GetParameterListOnVertices(&bed[0],BedEnum);
     4788                                        GetParameterListOnVertices(&surface[0],SurfaceEnum);
     4789
     4790                                        /*build new thickness: */
     4791//                                      for(j=0;j<6;j++)thickness[j]=values[j];
     4792
     4793                                        /*build new bed and surface: */
     4794                                        if (this->IsOnShelf()){
     4795                                                /*hydrostatic equilibrium: */
     4796                                                double rho_ice,rho_water,di;
     4797                                                rho_ice=this->matpar->GetRhoIce();
     4798                                                rho_water=this->matpar->GetRhoWater();
     4799
     4800                                                di=rho_ice/rho_water;
     4801
     4802                                                /*build new thickness: */
     4803                                                for (j=0; j<6; j++) {
     4804                                                /*  for observed/interpolated/hydrostatic thickness, remove scaling from any hydrostatic thickness  */
     4805                                                        if     (hydrostatic_ratio[j] >= 0.)
     4806                                                                thickness[j]=values[j]-(values[j]/thickness_init[j]-1.)*hydrostatic_ratio[j]*surface[j]/(1.-di);
     4807                                                /*  for minimum thickness, don't scale  */
     4808                                                        else
     4809                                                                thickness[j]=thickness_init[j];
     4810
     4811                                                /*  check the computed thickness and update bed  */
     4812                                                        if (thickness[j] < 0.)
     4813                                                                thickness[j]=1./(1.-di);
     4814                                                        bed[j]=surface[j]-thickness[j];
     4815                                                }
     4816
     4817//                                              for(j=0;j<6;j++){
     4818//                                                      surface[j]=(1-di)*thickness[j];
     4819//                                                      bed[j]=-di*thickness[j];
     4820//                                              }
     4821                                        }
     4822                                        else{
     4823                                                /*build new thickness: */
     4824                                                for (j=0; j<6; j++) {
     4825                                                /*  for observed thickness, use scaled value  */
     4826                                                        if(hydrostatic_ratio[j] >= 0.)
     4827                                                                thickness[j]=values[j];
     4828                                                /*  for minimum thickness, don't scale  */
     4829                                                        else
     4830                                                                thickness[j]=thickness_init[j];
     4831                                                }
     4832
     4833                                                /*update bed on grounded ice: */
     4834//                                              for(j=0;j<6;j++)surface[j]=bed[j]+thickness[j];
     4835                                                for(j=0;j<6;j++)bed[j]=surface[j]-thickness[j];
     4836                                        }
     4837
     4838                                        /*Add new inputs: */
     4839                                        this->inputs->AddInput(new PentaVertexInput(ThicknessEnum,thickness));
     4840                                        this->inputs->AddInput(new PentaVertexInput(BedEnum,bed));
     4841                                        this->inputs->AddInput(new PentaVertexInput(SurfaceEnum,surface));
     4842
     4843                                        /*}}}*/
     4844                                        break;
     4845                                default:
     4846                                        this->inputs->AddInput(new PentaVertexInput(name,values));
     4847                        }
     4848                        break;
     4849
     4850                default:
     4851                        _error_("type %i (%s) not implemented yet",type,EnumToStringx(type));
     4852        }
     4853
     4854}
     4855/*}}}*/
     4856/*FUNCTION Penta::InputUpdateFromVectorDakota(int* vector, int name, int type);{{{1*/
     4857void  Penta::InputUpdateFromVectorDakota(int* vector, int name, int type){
     4858        _error_(" not supported yet!");
     4859}
     4860/*}}}*/
     4861/*FUNCTION Penta::InputUpdateFromVectorDakota(bool* vector, int name, int type);{{{1*/
     4862void  Penta::InputUpdateFromVectorDakota(bool* vector, int name, int type){
     4863        _error_(" not supported yet!");
     4864}
     4865/*}}}*/
     4866#endif
     4867
     4868#ifdef _HAVE_DIAGNOSTIC_
     4869/*FUNCTION Penta::CreateDVectorDiagnosticHoriz {{{1*/
     4870ElementVector* Penta::CreateDVectorDiagnosticHoriz(void){
     4871
     4872        int approximation;
     4873        inputs->GetParameterValue(&approximation,ApproximationEnum);
     4874
     4875        switch(approximation){
     4876                case StokesApproximationEnum:
     4877                        return CreateDVectorDiagnosticStokes();
     4878                default:
     4879                        return NULL; //no need for doftypes outside of stokes approximation
     4880        }
     4881}
     4882/*}}}*/
     4883/*FUNCTION Penta::CreateDVectorDiagnosticStokes{{{1*/
     4884ElementVector* Penta::CreateDVectorDiagnosticStokes(void){
     4885
     4886        /*output: */
     4887        ElementVector* De=NULL;
     4888        /*intermediary: */
     4889        int approximation;
     4890        int i;
     4891
     4892        /*Initialize Element vector and return if necessary*/
     4893        inputs->GetParameterValue(&approximation,ApproximationEnum);
     4894        if(approximation!=StokesApproximationEnum) return NULL;
     4895
     4896        De=new ElementVector(nodes,NUMVERTICES,this->parameters,StokesApproximationEnum);
     4897
     4898        for (i=0;i<NUMVERTICES;i++){
     4899                De->values[i*4+0]=VelocityEnum;
     4900                De->values[i*4+1]=VelocityEnum;
     4901                De->values[i*4+2]=VelocityEnum;
     4902                De->values[i*4+3]=PressureEnum;
     4903        }
     4904
     4905        return De;
     4906}
     4907/*}}}*/
     4908/*FUNCTION Penta::CreateKMatrixCouplingMacAyealPattyn{{{1*/
     4909ElementMatrix* Penta::CreateKMatrixCouplingMacAyealPattyn(void){
     4910       
     4911        /*compute all stiffness matrices for this element*/
     4912        ElementMatrix* Ke1=CreateKMatrixCouplingMacAyealPattynViscous();
     4913        ElementMatrix* Ke2=CreateKMatrixCouplingMacAyealPattynFriction();
     4914        ElementMatrix* Ke=new ElementMatrix(Ke1,Ke2);
     4915       
     4916        /*clean-up and return*/
     4917        delete Ke1;
     4918        delete Ke2;
     4919        return Ke;
     4920}
     4921/*}}}*/
     4922/*FUNCTION Penta::CreateKMatrixCouplingMacAyealPattynViscous{{{1*/
     4923ElementMatrix* Penta::CreateKMatrixCouplingMacAyealPattynViscous(void){
     4924
     4925        /*Constants*/
     4926        const int    numdofm=NDOF2*NUMVERTICES2D;
     4927        const int    numdofp=NDOF2*NUMVERTICES;
     4928        const int    numdoftotal=2*NDOF2*NUMVERTICES;
     4929
     4930        /*Intermediaries */
     4931        int         i,j,ig;
     4932        double      Jdet;
     4933        double      viscosity,oldviscosity,newviscosity,viscosity_overshoot; //viscosity
     4934        double      epsilon[5],oldepsilon[5]; /* epsilon=[exx,eyy,exy,exz,eyz];*/
     4935        double      xyz_list[NUMVERTICES][3];
     4936        double      B[3][numdofp];
     4937        double      Bprime[3][numdofm];
     4938        double      D[3][3]={0.0};            // material matrix, simple scalar matrix.
     4939        double      D_scalar;
     4940        double      Ke_gg[numdofp][numdofm]={0.0}; //local element stiffness matrix
     4941        double      Ke_gg_gaussian[numdofp][numdofm]; //stiffness matrix evaluated at the gaussian point.
     4942        GaussPenta *gauss=NULL;
     4943        GaussTria  *gauss_tria=NULL;
     4944
     4945        /*Find penta on bed as pattyn must be coupled to the dofs on the bed: */
     4946        Penta* pentabase=GetBasalElement();
     4947        Tria* tria=pentabase->SpawnTria(0,1,2); //nodes 0, 1 and 2 make the new tria.
     4948
     4949        /*Initialize Element matrix*/
     4950        ElementMatrix* Ke1=new ElementMatrix(pentabase->nodes,NUMVERTICES,this->parameters,MacAyealApproximationEnum);
     4951        ElementMatrix* Ke2=new ElementMatrix(this->nodes     ,NUMVERTICES,this->parameters,PattynApproximationEnum);
     4952        ElementMatrix* Ke =new ElementMatrix(Ke1,Ke2);
     4953        delete Ke1; delete Ke2;
     4954
     4955        /* Get node coordinates and dof list: */
     4956        GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
     4957        this->parameters->FindParam(&viscosity_overshoot,DiagnosticViscosityOvershootEnum);
     4958        Input* vx_input=inputs->GetInput(VxEnum);       _assert_(vx_input);
     4959        Input* vy_input=inputs->GetInput(VyEnum);       _assert_(vy_input);
     4960        Input* vxold_input=inputs->GetInput(VxPicardEnum); _assert_(vxold_input);
     4961        Input* vyold_input=inputs->GetInput(VyPicardEnum); _assert_(vyold_input);
     4962
     4963        /* Start  looping on the number of gaussian points: */
     4964        gauss=new GaussPenta(5,5);
     4965        gauss_tria=new GaussTria();
     4966        for (ig=gauss->begin();ig<gauss->end();ig++){
     4967
     4968                gauss->GaussPoint(ig);
     4969                gauss->SynchronizeGaussTria(gauss_tria);
     4970
     4971                GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss);
     4972                GetBMacAyealPattyn(&B[0][0], &xyz_list[0][0], gauss);
     4973                tria->GetBprimeMacAyeal(&Bprime[0][0], &xyz_list[0][0], gauss_tria);
     4974
     4975                this->GetStrainRate3dPattyn(&epsilon[0],&xyz_list[0][0],gauss,vx_input,vy_input);
     4976                this->GetStrainRate3dPattyn(&oldepsilon[0],&xyz_list[0][0],gauss,vxold_input,vyold_input);
     4977                matice->GetViscosity3d(&viscosity, &epsilon[0]);
     4978                matice->GetViscosity3d(&oldviscosity, &oldepsilon[0]);
     4979
     4980                newviscosity=viscosity+viscosity_overshoot*(viscosity-oldviscosity);
     4981                D_scalar=2*newviscosity*gauss->weight*Jdet;
     4982                for (i=0;i<3;i++) D[i][i]=D_scalar;
     4983
     4984                TripleMultiply( &B[0][0],3,numdofp,1,
     4985                                        &D[0][0],3,3,0,
     4986                                        &Bprime[0][0],3,numdofm,0,
     4987                                        &Ke_gg_gaussian[0][0],0);
     4988
     4989                for( i=0; i<numdofp; i++) for(j=0;j<numdofm; j++) Ke_gg[i][j]+=Ke_gg_gaussian[i][j];
     4990        }
     4991        for(i=0;i<numdofp;i++) for(j=0;j<numdofm;j++) Ke->values[(i+2*numdofm)*numdoftotal+j]+=Ke_gg[i][j];
     4992        for(i=0;i<numdofm;i++) for(j=0;j<numdofp;j++) Ke->values[i*numdoftotal+(j+2*numdofm)]+=Ke_gg[j][i];
     4993
     4994        /*Clean-up and return*/
     4995        delete tria->matice; delete tria;
     4996        delete gauss;
     4997        delete gauss_tria;
     4998        return Ke;
     4999}
     5000/*}}}*/
     5001/*FUNCTION Penta::CreateKMatrixCouplingMacAyealPattynFriction{{{1*/
     5002ElementMatrix* Penta::CreateKMatrixCouplingMacAyealPattynFriction(void){
     5003
     5004        /*Constants*/
     5005        const int numdof        = NDOF2 *NUMVERTICES;
     5006        const int numdoftotal   = NDOF4 *NUMVERTICES;
     5007       
     5008        /*Intermediaries */
     5009        int       i,j,ig,analysis_type;
     5010        double    Jdet2d,slope_magnitude,alpha2;
     5011        double    xyz_list[NUMVERTICES][3];
     5012        double    xyz_list_tria[NUMVERTICES2D][3]={0.0};
     5013        double    slope[3]={0.0,0.0,0.0};
     5014        double    MAXSLOPE=.06; // 6 %
     5015        double    MOUNTAINKEXPONENT=10;
     5016        double    L[2][numdof];
     5017        double    DL[2][2]                  ={{ 0,0 },{0,0}}; //for basal drag
     5018        double    DL_scalar;
     5019        double    Ke_gg[numdof][numdof]     ={0.0};
     5020        double    Ke_gg_gaussian[numdof][numdof]; //stiffness matrix contribution from drag
     5021        Friction  *friction = NULL;
     5022        GaussPenta *gauss=NULL;
     5023
     5024        /*Initialize Element matrix and return if necessary*/
     5025        if(IsOnShelf() || !IsOnBed()) return NULL;
     5026        ElementMatrix* Ke1=new ElementMatrix(nodes,NUMVERTICES,this->parameters,MacAyealApproximationEnum);
     5027        ElementMatrix* Ke2=new ElementMatrix(nodes,NUMVERTICES,this->parameters,PattynApproximationEnum);
     5028        ElementMatrix* Ke=new ElementMatrix(Ke1,Ke2);
     5029        delete Ke1; delete Ke2;
     5030
     5031        /*retrieve inputs :*/
     5032        GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
     5033        for(i=0;i<NUMVERTICES2D;i++) for(j=0;j<2;j++) xyz_list_tria[i][j]=xyz_list[i][j];
     5034        parameters->FindParam(&analysis_type,AnalysisTypeEnum);
     5035        Input* surface_input=inputs->GetInput(SurfaceEnum); _assert_(surface_input);
     5036        Input* vx_input=inputs->GetInput(VxEnum);           _assert_(vx_input);
     5037        Input* vy_input=inputs->GetInput(VyEnum);           _assert_(vy_input);
     5038        Input* vz_input=inputs->GetInput(VzEnum);           _assert_(vz_input);
     5039
     5040        /*build friction object, used later on: */
     5041        friction=new Friction("2d",inputs,matpar,analysis_type);
     5042
     5043        /* Start  looping on the number of gaussian points: */
     5044        gauss=new GaussPenta(0,1,2,2);
     5045        for (ig=gauss->begin();ig<gauss->end();ig++){
     5046
     5047                gauss->GaussPoint(ig);
     5048
     5049                /*Friction: */
     5050                friction->GetAlpha2(&alpha2, gauss,VxEnum,VyEnum,VzEnum);
     5051
     5052                // If we have a slope > 6% for this element,  it means  we are on a mountain. In this particular case,
     5053                //velocity should be = 0. To achieve this result, we set alpha2_list to a very high value: */
     5054                surface_input->GetParameterDerivativeValue(&slope[0],&xyz_list[0][0],gauss);
     5055                slope_magnitude=sqrt(pow(slope[0],2)+pow(slope[1],2));
     5056
     5057                if (slope_magnitude>MAXSLOPE){
     5058                        alpha2=pow((double)10,MOUNTAINKEXPONENT);
     5059                }
     5060
     5061                GetTriaJacobianDeterminant(&Jdet2d, &xyz_list_tria[0][0],gauss);
     5062                GetL(&L[0][0], gauss,NDOF2);
     5063
     5064                DL_scalar=alpha2*gauss->weight*Jdet2d;
     5065                for (i=0;i<2;i++) DL[i][i]=DL_scalar;
     5066               
     5067                /*  Do the triple producte tL*D*L: */
     5068                TripleMultiply( &L[0][0],2,numdof,1,
     5069                                        &DL[0][0],2,2,0,
     5070                                        &L[0][0],2,numdof,0,
     5071                                        &Ke_gg_gaussian[0][0],0);
     5072
     5073                for(i=0;i<numdof;i++) for(j=0;j<numdof;j++) Ke_gg[i][j]+=Ke_gg_gaussian[i][j];
     5074        }
     5075
     5076        for(i=0;i<numdof;i++) for(j=0;j<numdof;j++) Ke->values[i*numdoftotal+(numdof+j)]+=Ke_gg[i][j];
     5077        for(i=0;i<numdof;i++) for(j=0;j<numdof;j++) Ke->values[(i+numdof)*numdoftotal+j]+=Ke_gg[i][j];
     5078
     5079        /*Clean up and return*/
     5080        delete gauss;
     5081        delete friction;
     5082        return Ke;
     5083}
     5084/*}}}*/
     5085/*FUNCTION Penta::CreateKMatrixCouplingMacAyealStokes{{{1*/
     5086ElementMatrix* Penta::CreateKMatrixCouplingMacAyealStokes(void){
     5087
     5088        /*compute all stiffness matrices for this element*/
     5089        ElementMatrix* Ke1=CreateKMatrixCouplingMacAyealStokesViscous();
     5090        ElementMatrix* Ke2=CreateKMatrixCouplingMacAyealStokesFriction();
     5091        ElementMatrix* Ke =new ElementMatrix(Ke1,Ke2);
     5092
     5093        /*clean-up and return*/
     5094        delete Ke1;
     5095        delete Ke2;
     5096        return Ke;
     5097}
     5098/*}}}*/
     5099/*FUNCTION Penta::CreateKMatrixCouplingMacAyealStokesViscous{{{1*/
     5100ElementMatrix* Penta::CreateKMatrixCouplingMacAyealStokesViscous(void){
     5101
     5102        /*Constants*/
     5103        const int    numdofm=NDOF2*NUMVERTICES2D;
     5104        const int    numdofs=NDOF4*NUMVERTICES;
     5105        const int    numdoftotal=2*numdofm+numdofs;
     5106
     5107        /*Intermediaries */
     5108        int         i,j,ig;
     5109        double      Jdet;
     5110        double      viscosity,stokesreconditioning; //viscosity
     5111        double      epsilon[6]; /* epsilon=[exx,eyy,exy,exz,eyz];*/
     5112        double      xyz_list[NUMVERTICES][3];
     5113        double      B[4][numdofs+3];
     5114        double      Bprime[4][numdofm];
     5115        double      B2[3][numdofm];
     5116        double      Bprime2[3][numdofs+3];
     5117        double      D[4][4]={0.0};            // material matrix, simple scalar matrix.
     5118        double      D2[3][3]={0.0};            // material matrix, simple scalar matrix.
     5119        double      D_scalar;
     5120        double      Ke_gg[numdofs][numdofm]={0.0}; //local element stiffness matrix
     5121        double      Ke_gg2[numdofm][numdofs]={0.0}; //local element stiffness matrix
     5122        double      Ke_gg_gaussian[numdofs+3][numdofm]; //stiffness matrix evaluated at the gaussian point.
     5123        double      Ke_gg_gaussian2[numdofm][numdofs+3]; //stiffness matrix evaluated at the gaussian point.
     5124        GaussPenta *gauss=NULL;
     5125        GaussTria  *gauss_tria=NULL;
     5126
     5127        /*Find penta on bed as stokes must be coupled to the dofs on the bed: */
     5128        Penta* pentabase=GetBasalElement();
     5129        Tria* tria=pentabase->SpawnTria(0,1,2); //nodes 0, 1 and 2 make the new tria.
     5130
     5131        /*Initialize Element matrix and return if necessary*/
     5132        ElementMatrix* Ke1=new ElementMatrix(pentabase->nodes,NUMVERTICES,this->parameters,MacAyealApproximationEnum);
     5133        ElementMatrix* Ke2=new ElementMatrix(this->nodes     ,NUMVERTICES,this->parameters,StokesApproximationEnum);
     5134        ElementMatrix* Ke=new ElementMatrix(Ke1,Ke2);
     5135        delete Ke1; delete Ke2;
     5136
     5137        /* Get node coordinates and dof list: */
     5138        GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
     5139        parameters->FindParam(&stokesreconditioning,DiagnosticStokesreconditioningEnum);
     5140        Input* vx_input=inputs->GetInput(VxEnum);       _assert_(vx_input);
     5141        Input* vy_input=inputs->GetInput(VyEnum);       _assert_(vy_input);
     5142        Input* vz_input=inputs->GetInput(VzEnum);       _assert_(vz_input);
     5143
     5144        /* Start  looping on the number of gaussian points: */
     5145        gauss=new GaussPenta(5,5);
     5146        gauss_tria=new GaussTria();
     5147        for (ig=gauss->begin();ig<gauss->end();ig++){
     5148
     5149                gauss->GaussPoint(ig);
     5150                gauss->SynchronizeGaussTria(gauss_tria);
     5151
     5152                GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss);
     5153                GetBMacAyealStokes(&B[0][0], &xyz_list[0][0], gauss);
     5154                tria->GetBprimeMacAyealStokes(&Bprime[0][0], &xyz_list[0][0], gauss_tria);
     5155                tria->GetBMacAyealStokes(&B2[0][0], &xyz_list[0][0], gauss_tria);
     5156                GetBprimeMacAyealStokes(&Bprime2[0][0], &xyz_list[0][0], gauss);
     5157
     5158                this->GetStrainRate3d(&epsilon[0],&xyz_list[0][0],gauss,vx_input,vy_input,vz_input);
     5159                matice->GetViscosity3dStokes(&viscosity, &epsilon[0]);
     5160
     5161                D_scalar=2*viscosity*gauss->weight*Jdet;
     5162                for (i=0;i<3;i++) D[i][i]=D_scalar;
     5163                D[3][3]=-gauss->weight*Jdet*stokesreconditioning;
     5164                for (i=0;i<3;i++) D2[i][i]=D_scalar;
     5165
     5166                TripleMultiply( &B[0][0],4,numdofs+3,1,
     5167                                        &D[0][0],4,4,0,
     5168                                        &Bprime[0][0],4,numdofm,0,
     5169                                        &Ke_gg_gaussian[0][0],0);
     5170
     5171                TripleMultiply( &B2[0][0],3,numdofm,1,
     5172                                        &D2[0][0],3,3,0,
     5173                                        &Bprime2[0][0],3,numdofs+3,0,
     5174                                        &Ke_gg_gaussian2[0][0],0);
     5175
     5176                for( i=0; i<numdofs; i++) for(j=0;j<numdofm; j++) Ke_gg[i][j]+=Ke_gg_gaussian[i][j];
     5177                for( i=0; i<numdofm; i++) for(j=0;j<numdofs; j++) Ke_gg2[i][j]+=Ke_gg_gaussian2[i][j];
     5178        }
     5179        for(i=0;i<numdofs;i++) for(j=0;j<numdofm;j++) Ke->values[(i+2*numdofm)*numdoftotal+j]+=Ke_gg[i][j];
     5180        for(i=0;i<numdofm;i++) for(j=0;j<numdofs;j++) Ke->values[i*numdoftotal+(j+2*numdofm)]+=Ke_gg2[i][j];
     5181
     5182        /*Clean-up and return*/
     5183        delete tria->matice; delete tria;
     5184        delete gauss;
     5185        delete gauss_tria;
     5186        return Ke;
     5187}
     5188/*}}}*/
     5189/*FUNCTION Penta::CreateKMatrixCouplingMacAyealStokesFriction {{{1*/
     5190ElementMatrix* Penta::CreateKMatrixCouplingMacAyealStokesFriction(void){
     5191
     5192        /*Constants*/
     5193        const int numdof=NUMVERTICES*NDOF4;
     5194        const int numdofm=NUMVERTICES*NDOF2;
     5195        const int numdof2d=NUMVERTICES2D*NDOF4;
     5196        const int numdof2dm=NUMVERTICES2D*NDOF2;
     5197        const int numdoftot=numdof+numdofm;
     5198
     5199        /*Intermediaries */
     5200        int        i,j,ig;
     5201        int        analysis_type,approximation;
     5202        double     stokesreconditioning;
     5203        double     viscosity,alpha2_gauss,Jdet2d;
     5204        double    bed_normal[3];
     5205        double     epsilon[6]; /* epsilon=[exx,eyy,ezz,exy,exz,eyz];*/
     5206        double     xyz_list[NUMVERTICES][3];
     5207        double    xyz_list_tria[NUMVERTICES2D][3];
     5208        double     LMacAyealStokes[8][numdof2dm];
     5209        double     LprimeMacAyealStokes[8][numdof2d];
     5210        double     DLMacAyealStokes[8][8]={0.0};
     5211        double     LStokesMacAyeal[4][numdof2d];
     5212        double     LprimeStokesMacAyeal[4][numdof2dm];
     5213        double     DLStokesMacAyeal[4][4]={0.0};
     5214        double     Ke_drag_gaussian[numdof2dm][numdof2d];
     5215        double     Ke_drag_gaussian2[numdof2d][numdof2dm];
     5216        Friction*  friction=NULL;
     5217        GaussPenta *gauss=NULL;
     5218
     5219        /*If on water or not Stokes, skip stiffness: */
     5220        inputs->GetParameterValue(&approximation,ApproximationEnum);
     5221        if(IsOnShelf() || !IsOnBed()) return NULL;
     5222        ElementMatrix* Ke1=new ElementMatrix(this->nodes,NUMVERTICES,this->parameters,MacAyealApproximationEnum);
     5223        ElementMatrix* Ke2=new ElementMatrix(this->nodes,NUMVERTICES,this->parameters,StokesApproximationEnum);
     5224        ElementMatrix* Ke=new ElementMatrix(Ke1,Ke2);
     5225        delete Ke1; delete Ke2;
     5226
     5227        /*Retrieve all inputs and parameters*/
     5228        GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
     5229        parameters->FindParam(&analysis_type,AnalysisTypeEnum);
     5230        parameters->FindParam(&stokesreconditioning,DiagnosticStokesreconditioningEnum);
     5231        Input* vx_input=inputs->GetInput(VxEnum); _assert_(vx_input);
     5232        Input* vy_input=inputs->GetInput(VyEnum); _assert_(vy_input);
     5233        Input* vz_input=inputs->GetInput(VzEnum); _assert_(vz_input);
     5234        for(i=0;i<NUMVERTICES2D;i++) for(j=0;j<3;j++) xyz_list_tria[i][j]=xyz_list[i][j];
     5235
     5236        /*build friction object, used later on: */
     5237        friction=new Friction("3d",inputs,matpar,analysis_type);
     5238
     5239        /* Start  looping on the number of gaussian points: */
     5240        gauss=new GaussPenta(0,1,2,2);
     5241        for (ig=gauss->begin();ig<gauss->end();ig++){
     5242
     5243                gauss->GaussPoint(ig);
     5244
     5245                GetTriaJacobianDeterminant(&Jdet2d, &xyz_list_tria[0][0],gauss);
     5246                GetLMacAyealStokes(&LMacAyealStokes[0][0], gauss);
     5247                GetLprimeMacAyealStokes(&LprimeMacAyealStokes[0][0], &xyz_list[0][0], gauss);
     5248                GetLStokesMacAyeal(&LStokesMacAyeal[0][0], gauss);
     5249                GetLprimeStokesMacAyeal(&LprimeStokesMacAyeal[0][0], &xyz_list[0][0], gauss);
     5250
     5251                this->GetStrainRate3d(&epsilon[0],&xyz_list[0][0],gauss,vx_input,vy_input,vz_input);
     5252                matice->GetViscosity3dStokes(&viscosity,&epsilon[0]);
     5253
     5254                BedNormal(&bed_normal[0],xyz_list_tria);
     5255                friction->GetAlpha2(&alpha2_gauss, gauss,VxEnum,VyEnum,VzEnum);
     5256
     5257                DLMacAyealStokes[0][0]=alpha2_gauss*gauss->weight*Jdet2d;
     5258                DLMacAyealStokes[1][1]=alpha2_gauss*gauss->weight*Jdet2d;
     5259                DLMacAyealStokes[2][2]=-alpha2_gauss*gauss->weight*Jdet2d*bed_normal[0]*bed_normal[2];
     5260                DLMacAyealStokes[3][3]=-alpha2_gauss*gauss->weight*Jdet2d*bed_normal[1]*bed_normal[2];
     5261                DLMacAyealStokes[4][4]=-2*viscosity*gauss->weight*Jdet2d*bed_normal[0];
     5262                DLMacAyealStokes[5][5]=-2*viscosity*gauss->weight*Jdet2d*bed_normal[1];
     5263                DLMacAyealStokes[6][6]=stokesreconditioning*gauss->weight*Jdet2d*bed_normal[0];
     5264                DLMacAyealStokes[7][7]=stokesreconditioning*gauss->weight*Jdet2d*bed_normal[1];
     5265
     5266                DLStokesMacAyeal[0][0]=alpha2_gauss*gauss->weight*Jdet2d;
     5267                DLStokesMacAyeal[1][1]=alpha2_gauss*gauss->weight*Jdet2d;
     5268                DLStokesMacAyeal[2][2]=-alpha2_gauss*gauss->weight*Jdet2d*bed_normal[0]*bed_normal[2];
     5269                DLStokesMacAyeal[3][3]=-alpha2_gauss*gauss->weight*Jdet2d*bed_normal[1]*bed_normal[2];
     5270               
     5271                TripleMultiply( &LMacAyealStokes[0][0],8,numdof2dm,1,
     5272                                        &DLMacAyealStokes[0][0],8,8,0,
     5273                                        &LprimeMacAyealStokes[0][0],8,numdof2d,0,
     5274                                        &Ke_drag_gaussian[0][0],0);
     5275
     5276                TripleMultiply( &LStokesMacAyeal[0][0],4,numdof2d,1,
     5277                                        &DLStokesMacAyeal[0][0],4,4,0,
     5278                                        &LprimeStokesMacAyeal[0][0],4,numdof2dm,0,
     5279                                        &Ke_drag_gaussian2[0][0],0);
     5280
     5281                for(i=0;i<numdof2dm;i++) for(j=0;j<numdof2d;j++) Ke->values[i*numdoftot+j+numdofm]+=Ke_drag_gaussian[i][j];
     5282                for(i=0;i<numdof2d;i++) for(j=0;j<numdof2dm;j++) Ke->values[(i+numdofm)*numdoftot+j]+=Ke_drag_gaussian2[i][j];
     5283        }
     5284
     5285        /*Clean up and return*/
     5286        delete gauss;
     5287        delete friction;
     5288        return Ke;
     5289}
     5290/*}}}*/
     5291/*FUNCTION Penta::CreateKMatrixCouplingPattynStokes{{{1*/
     5292ElementMatrix* Penta::CreateKMatrixCouplingPattynStokes(void){
     5293
     5294        /*compute all stiffness matrices for this element*/
     5295        ElementMatrix* Ke1=new ElementMatrix(this->nodes,NUMVERTICES,this->parameters,PattynApproximationEnum);
     5296        ElementMatrix* Ke2=new ElementMatrix(this->nodes,NUMVERTICES,this->parameters,StokesApproximationEnum);
     5297        ElementMatrix* Ke=new ElementMatrix(Ke1,Ke2);
     5298        delete Ke1;
     5299        delete Ke2;
     5300        Ke1=CreateKMatrixDiagnosticPattyn();
     5301        Ke2=CreateKMatrixDiagnosticStokes();
     5302
     5303        /*Constants*/
     5304        const int    numdofp=NDOF2*NUMVERTICES;
     5305        const int    numdofs=NDOF4*NUMVERTICES;
     5306        const int    numdoftotal=(NDOF2+NDOF4)*NUMVERTICES;
     5307        int          i,j;
     5308
     5309        for(i=0;i<numdofs;i++) for(j=0;j<NUMVERTICES;j++){
     5310                Ke->values[(i+numdofp)*numdoftotal+NDOF2*j+0]+=Ke2->values[i*numdofs+NDOF4*j+0];
     5311                Ke->values[(i+numdofp)*numdoftotal+NDOF2*j+1]+=Ke2->values[i*numdofs+NDOF4*j+1];
     5312        }
     5313        for(i=0;i<numdofp;i++) for(j=0;j<NUMVERTICES;j++){
     5314                Ke->values[i*numdoftotal+numdofp+NDOF4*j+0]+=Ke1->values[i*numdofp+NDOF2*j+0];
     5315                Ke->values[i*numdoftotal+numdofp+NDOF4*j+1]+=Ke1->values[i*numdofp+NDOF2*j+1];
     5316        }
     5317
     5318        /*clean-up and return*/
     5319        delete Ke1;
     5320        delete Ke2;
     5321        return Ke;
     5322}
     5323/*}}}*/
     5324/*FUNCTION Penta::CreateKMatrixDiagnosticHoriz {{{1*/
     5325ElementMatrix* Penta::CreateKMatrixDiagnosticHoriz(void){
     5326
     5327        int approximation;
     5328        inputs->GetParameterValue(&approximation,ApproximationEnum);
     5329
     5330        switch(approximation){
     5331                case MacAyealApproximationEnum:
     5332                        return CreateKMatrixDiagnosticMacAyeal2d();
     5333                case PattynApproximationEnum:
     5334                        return CreateKMatrixDiagnosticPattyn();
     5335                case StokesApproximationEnum:
     5336                        return CreateKMatrixDiagnosticStokes();
     5337                case HutterApproximationEnum:
     5338                        return NULL;
     5339                case NoneApproximationEnum:
     5340                        return NULL;
     5341                case MacAyealPattynApproximationEnum:
     5342                        return CreateKMatrixDiagnosticMacAyealPattyn();
     5343                case MacAyealStokesApproximationEnum:
     5344                        return CreateKMatrixDiagnosticMacAyealStokes();
     5345                case PattynStokesApproximationEnum:
     5346                        return CreateKMatrixDiagnosticPattynStokes();
     5347                default:
     5348                        _error_("Approximation %s not supported yet",EnumToStringx(approximation));
     5349        }
     5350}
     5351/*}}}*/
     5352/*FUNCTION Penta::CreateKMatrixDiagnosticHutter{{{1*/
     5353ElementMatrix* Penta::CreateKMatrixDiagnosticHutter(void){
     5354
     5355        /*Constants*/
     5356        const int numdof=NDOF2*NUMVERTICES;
     5357
     5358        /*Intermediaries*/
     5359        int       connectivity[2];
     5360        int       i,i0,i1,j0,j1;
     5361        double    one0,one1;
     5362
     5363        /*Initialize Element matrix*/
     5364        ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,NoneApproximationEnum);
     5365
     5366        /*Spawn 3 beam elements: */
     5367        for(i=0;i<3;i++){
     5368                /*2 dofs of first node*/
     5369                i0=2*i;
     5370                i1=2*i+1;
     5371                /*2 dofs of second node*/
     5372                j0=2*(i+3);
     5373                j1=2*(i+3)+1;
     5374
     5375                /*Find connectivity for the two nodes*/
     5376                connectivity[0]=nodes[i]->GetConnectivity();
     5377                connectivity[1]=nodes[i+3]->GetConnectivity();
     5378                one0=1/(double)connectivity[0];
     5379                one1=1/(double)connectivity[1];
     5380
     5381                /*Create matrix for these two nodes*/
     5382                if (IsOnBed() && IsOnSurface()){
     5383                        Ke->values[i0*numdof+i0]=one0;
     5384                        Ke->values[i1*numdof+i1]=one0;
     5385                        Ke->values[j0*numdof+i0]=-one1;
     5386                        Ke->values[j0*numdof+j0]=one1;
     5387                        Ke->values[j1*numdof+i1]=-one1;
     5388                        Ke->values[j1*numdof+j1]=one1;
     5389                }
     5390                else if (IsOnBed()){
     5391                        Ke->values[i0*numdof+i0]=one0;
     5392                        Ke->values[i1*numdof+i1]=one0;
     5393                        Ke->values[j0*numdof+i0]=-2*one1;
     5394                        Ke->values[j0*numdof+j0]=2*one1;
     5395                        Ke->values[j1*numdof+i1]=-2*one1;
     5396                        Ke->values[j1*numdof+j1]=2*one1;
     5397                }
     5398                else if (IsOnSurface()){
     5399                        Ke->values[j0*numdof+i0]=-one1;
     5400                        Ke->values[j0*numdof+j0]=one1;
     5401                        Ke->values[j1*numdof+i1]=-one1;
     5402                        Ke->values[j1*numdof+j1]=one1;
     5403                }
     5404                else{ //node is on two horizontal layers and beams include the values only once, so the have to use half of the connectivity
     5405                        Ke->values[j0*numdof+i0]=-2*one1;
     5406                        Ke->values[j0*numdof+j0]=2*one1;
     5407                        Ke->values[j1*numdof+i1]=-2*one1;
     5408                        Ke->values[j1*numdof+j1]=2*one1;
     5409                }
     5410        }
     5411
     5412        /*Clean up and return*/
     5413        return Ke;
     5414}
     5415/*FUNCTION Penta::CreateKMatrixDiagnosticMacAyeal2d{{{1*/
     5416ElementMatrix* Penta::CreateKMatrixDiagnosticMacAyeal2d(void){
     5417
     5418        /*Figure out if this penta is collapsed. If so, then bailout, except if it is at the
     5419          bedrock, in which case we spawn a tria element using the 3 first nodes, and use it to build
     5420          the stiffness matrix. */
     5421        if (!IsOnBed()) return NULL;
     5422
     5423        /*Depth Averaging B*/
     5424        this->InputDepthAverageAtBase(MaterialsRheologyBEnum,MaterialsRheologyBbarEnum,MaterialsEnum);
     5425
     5426        /*Call Tria function*/
     5427        Tria* tria=(Tria*)SpawnTria(0,1,2); //nodes 0, 1 and 2 make the new tria.
     5428        ElementMatrix* Ke=tria->CreateKMatrixDiagnosticMacAyeal();
     5429        delete tria->matice; delete tria;
     5430
     5431        /*Delete B averaged*/
     5432        this->matice->inputs->DeleteInput(MaterialsRheologyBbarEnum);
     5433
     5434        /*clean up and return*/
     5435        return Ke;
     5436}
     5437/*}}}*/
     5438/*FUNCTION Penta::CreateKMatrixDiagnosticMacAyeal3d{{{1*/
     5439ElementMatrix* Penta::CreateKMatrixDiagnosticMacAyeal3d(void){
     5440
     5441        /*compute all stiffness matrices for this element*/
     5442        ElementMatrix* Ke1=CreateKMatrixDiagnosticMacAyeal3dViscous();
     5443        ElementMatrix* Ke2=CreateKMatrixDiagnosticMacAyeal3dFriction();
     5444        ElementMatrix* Ke =new ElementMatrix(Ke1,Ke2);
     5445
     5446        /*clean-up and return*/
     5447        delete Ke1;
     5448        delete Ke2;
     5449        return Ke;
     5450}
     5451/*}}}*/
     5452/*FUNCTION Penta::CreateKMatrixDiagnosticMacAyeal3dViscous{{{1*/
     5453ElementMatrix* Penta::CreateKMatrixDiagnosticMacAyeal3dViscous(void){
     5454
     5455        /*Constants*/
     5456        const int    numdof2d=2*NUMVERTICES2D;
     5457
     5458        /*Intermediaries */
     5459        int         i,j,ig,approximation;
     5460        double      Jdet;
     5461        double      viscosity, oldviscosity, newviscosity, viscosity_overshoot;
     5462        double      epsilon[5],oldepsilon[5]; /* epsilon=[exx,eyy,exy,exz,eyz];*/
     5463        double      epsilons[6]; //6 for stokes
     5464        double      xyz_list[NUMVERTICES][3];
     5465        double      B[3][numdof2d];
     5466        double      Bprime[3][numdof2d];
     5467        double      D[3][3]={0.0};            // material matrix, simple scalar matrix.
     5468        double      D_scalar;
     5469        double      Ke_gg_gaussian[numdof2d][numdof2d]; //stiffness matrix evaluated at the gaussian point.
     5470        Tria*       tria=NULL;
     5471        Penta*      pentabase=NULL;
     5472        GaussPenta *gauss=NULL;
     5473        GaussTria  *gauss_tria=NULL;
     5474
     5475        /*Find penta on bed as this is a macayeal elements: */
     5476        pentabase=GetBasalElement();
     5477        tria=pentabase->SpawnTria(0,1,2); //nodes 0, 1 and 2 make the new tria.
     5478
     5479        /*Initialize Element matrix*/
     5480        ElementMatrix* Ke=new ElementMatrix(tria->nodes,NUMVERTICES2D,this->parameters,MacAyealApproximationEnum);
     5481        inputs->GetParameterValue(&approximation,ApproximationEnum);
     5482
     5483        /*Retrieve all inputs and parameters*/
     5484        GetVerticesCoordinates(&xyz_list[0][0], nodes,NUMVERTICES);
     5485        this->parameters->FindParam(&viscosity_overshoot,DiagnosticViscosityOvershootEnum);
     5486        Input* vx_input=inputs->GetInput(VxEnum);       _assert_(vx_input);
     5487        Input* vy_input=inputs->GetInput(VyEnum);       _assert_(vy_input);
     5488        Input* vxold_input=inputs->GetInput(VxPicardEnum); _assert_(vxold_input);
     5489        Input* vyold_input=inputs->GetInput(VyPicardEnum); _assert_(vyold_input);
     5490        Input* vz_input=inputs->GetInput(VzEnum);       _assert_(vz_input);
     5491
     5492        /* Start  looping on the number of gaussian points: */
     5493        gauss=new GaussPenta(5,5);
     5494        gauss_tria=new GaussTria();
     5495        for (ig=gauss->begin();ig<gauss->end();ig++){
     5496
     5497                gauss->GaussPoint(ig);
     5498                gauss->SynchronizeGaussTria(gauss_tria);
     5499
     5500                GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss);
     5501                tria->GetBMacAyeal(&B[0][0], &xyz_list[0][0], gauss_tria);
     5502                tria->GetBprimeMacAyeal(&Bprime[0][0], &xyz_list[0][0], gauss_tria);
     5503
     5504                if(approximation==MacAyealPattynApproximationEnum){
     5505                        this->GetStrainRate3dPattyn(&epsilon[0],&xyz_list[0][0],gauss,vx_input,vy_input);
     5506                        this->GetStrainRate3dPattyn(&oldepsilon[0],&xyz_list[0][0],gauss,vxold_input,vyold_input);
     5507                        matice->GetViscosity3d(&viscosity, &epsilon[0]);
     5508                        matice->GetViscosity3d(&oldviscosity, &oldepsilon[0]);
     5509
     5510                        newviscosity=viscosity+viscosity_overshoot*(viscosity-oldviscosity);
     5511                }
     5512                else if (approximation==MacAyealStokesApproximationEnum){
     5513                        this->GetStrainRate3d(&epsilons[0],&xyz_list[0][0],gauss,vx_input,vy_input,vz_input);
     5514                        matice->GetViscosity3dStokes(&newviscosity,&epsilons[0]);
     5515                }
     5516                else _error_("approximation %i (%s) not supported yet",approximation,EnumToStringx(approximation));
     5517
     5518                D_scalar=2*newviscosity*gauss->weight*Jdet;
     5519                for (i=0;i<3;i++) D[i][i]=D_scalar;
     5520
     5521                TripleMultiply( &B[0][0],3,numdof2d,1,
     5522                                        &D[0][0],3,3,0,
     5523                                        &Bprime[0][0],3,numdof2d,0,
     5524                                        &Ke_gg_gaussian[0][0],0);
     5525
     5526                for(i=0;i<numdof2d;i++) for(j=0;j<numdof2d;j++) Ke->values[i*numdof2d+j]+=Ke_gg_gaussian[i][j];
     5527        }
     5528
     5529        /*Clean up and return*/
     5530        delete tria->matice;
     5531        delete tria;
     5532        delete gauss_tria;
     5533        delete gauss;
     5534        return Ke;
     5535}
     5536/*}}}*/
     5537/*FUNCTION Penta::CreateKMatrixDiagnosticMacAyeal3dFriction{{{1*/
     5538ElementMatrix* Penta::CreateKMatrixDiagnosticMacAyeal3dFriction(void){
     5539
     5540        /*Initialize Element matrix and return if necessary*/
     5541        if(IsOnShelf() || !IsOnBed()) return NULL;
     5542
     5543        /*Build a tria element using the 3 nodes of the base of the penta. Then use
     5544         * the tria functionality to build a friction stiffness matrix on these 3
     5545         * nodes: */
     5546        Tria* tria=(Tria*)SpawnTria(0,1,2); //nodes 0, 1 and 2 make the new tria.
     5547        ElementMatrix* Ke=tria->CreateKMatrixDiagnosticMacAyealFriction();
     5548        delete tria->matice; delete tria;
     5549
     5550        /*clean-up and return*/
     5551        return Ke;
     5552}
     5553/*}}}*/
     5554/*FUNCTION Penta::CreateKMatrixDiagnosticMacAyealPattyn{{{1*/
     5555ElementMatrix* Penta::CreateKMatrixDiagnosticMacAyealPattyn(void){
     5556
     5557        /*compute all stiffness matrices for this element*/
     5558        ElementMatrix* Ke1=CreateKMatrixDiagnosticMacAyeal3d();
     5559        ElementMatrix* Ke2=CreateKMatrixDiagnosticPattyn();
     5560        ElementMatrix* Ke3=CreateKMatrixCouplingMacAyealPattyn();
     5561        ElementMatrix* Ke =new ElementMatrix(Ke1,Ke2,Ke3);
     5562
     5563        /*clean-up and return*/
     5564        delete Ke1;
     5565        delete Ke2;
     5566        delete Ke3;
     5567        return Ke;
     5568}
     5569/*}}}*/
     5570/*FUNCTION Penta::CreateKMatrixDiagnosticMacAyealStokes{{{1*/
     5571ElementMatrix* Penta::CreateKMatrixDiagnosticMacAyealStokes(void){
     5572
     5573        /*compute all stiffness matrices for this element*/
     5574        ElementMatrix* Ke1=CreateKMatrixDiagnosticMacAyeal3d();
     5575        ElementMatrix* Ke2=CreateKMatrixDiagnosticStokes();
     5576        ElementMatrix* Ke3=CreateKMatrixCouplingMacAyealStokes();
     5577        ElementMatrix* Ke =new ElementMatrix(Ke1,Ke2,Ke3);
     5578
     5579        /*clean-up and return*/
     5580        delete Ke1;
     5581        delete Ke2;
     5582        delete Ke3;
     5583        return Ke;
     5584}
     5585/*}}}*/
     5586/*FUNCTION Penta::CreateKMatrixDiagnosticPattyn{{{1*/
     5587ElementMatrix* Penta::CreateKMatrixDiagnosticPattyn(void){
     5588
     5589        /*compute all stiffness matrices for this element*/
     5590        ElementMatrix* Ke1=CreateKMatrixDiagnosticPattynViscous();
     5591        ElementMatrix* Ke2=CreateKMatrixDiagnosticPattynFriction();
     5592        ElementMatrix* Ke =new ElementMatrix(Ke1,Ke2);
     5593
     5594        /*clean-up and return*/
     5595        delete Ke1;
     5596        delete Ke2;
     5597        return Ke;
     5598
     5599}
     5600/*}}}*/
     5601/*FUNCTION Penta::CreateKMatrixDiagnosticPattynViscous{{{1*/
     5602ElementMatrix* Penta::CreateKMatrixDiagnosticPattynViscous(void){
     5603
     5604        /*Constants*/
     5605        const int    numdof=NDOF2*NUMVERTICES;
     5606
     5607        /*Intermediaries */
     5608        int        i,j,ig;
     5609        int        approximation;
     5610        double     xyz_list[NUMVERTICES][3];
     5611        double     Jdet;
     5612        double     viscosity,oldviscosity,newviscosity,viscosity_overshoot; //viscosity
     5613        double     epsilon[5],oldepsilon[5]; /* epsilon=[exx,eyy,exy,exz,eyz];*/
     5614        double     D_scalar;
     5615        double     D[5][5]={0.0};            // material matrix, simple scalar matrix.
     5616        double     B[5][numdof];
     5617        double     Bprime[5][numdof];
     5618        Tria*      tria=NULL;
     5619        GaussPenta *gauss=NULL;
     5620
     5621        /*Initialize Element matrix*/
     5622        ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,PattynApproximationEnum);
     5623
     5624        /*Retrieve all inputs and parameters*/
     5625        inputs->GetParameterValue(&approximation,ApproximationEnum);
     5626        GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
     5627        this->parameters->FindParam(&viscosity_overshoot,DiagnosticViscosityOvershootEnum);
     5628        Input* vx_input=inputs->GetInput(VxEnum);       _assert_(vx_input);
     5629        Input* vy_input=inputs->GetInput(VyEnum);       _assert_(vy_input);
     5630        Input* vxold_input=inputs->GetInput(VxPicardEnum); _assert_(vxold_input);
     5631        Input* vyold_input=inputs->GetInput(VyPicardEnum); _assert_(vyold_input);
     5632
     5633        /* Start  looping on the number of gaussian points: */
     5634        gauss=new GaussPenta(5,5);
     5635        for (ig=gauss->begin();ig<gauss->end();ig++){
     5636
     5637                gauss->GaussPoint(ig);
     5638
     5639                GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss);
     5640                GetBPattyn(&B[0][0], &xyz_list[0][0], gauss);
     5641                GetBprimePattyn(&Bprime[0][0], &xyz_list[0][0], gauss);
     5642
     5643                this->GetStrainRate3dPattyn(&epsilon[0],&xyz_list[0][0],gauss,vx_input,vy_input);
     5644                this->GetStrainRate3dPattyn(&oldepsilon[0],&xyz_list[0][0],gauss,vxold_input,vyold_input);
     5645                matice->GetViscosity3d(&viscosity, &epsilon[0]);
     5646                matice->GetViscosity3d(&oldviscosity, &oldepsilon[0]);
     5647                newviscosity=viscosity+viscosity_overshoot*(viscosity-oldviscosity);
     5648
     5649                D_scalar=2*newviscosity*gauss->weight*Jdet;
     5650                for (i=0;i<5;i++) D[i][i]=D_scalar;
     5651
     5652                TripleMultiply( &B[0][0],5,numdof,1,
     5653                                        &D[0][0],5,5,0,
     5654                                        &Bprime[0][0],5,numdof,0,
     5655                                        &Ke->values[0],1);
     5656        }
     5657
     5658        /*Clean up and return*/
     5659        delete gauss;
     5660        return Ke;
     5661}
     5662/*}}}*/
     5663/*FUNCTION Penta::CreateKMatrixDiagnosticPattynFriction{{{1*/
     5664ElementMatrix* Penta::CreateKMatrixDiagnosticPattynFriction(void){
     5665
     5666        /*Constants*/
     5667        const int numdof   = NDOF2*NUMVERTICES;
     5668       
     5669        /*Intermediaries */
     5670        int       i,j,ig;
     5671        int       analysis_type;
     5672        double    xyz_list[NUMVERTICES][3];
     5673        double    xyz_list_tria[NUMVERTICES2D][3]={0.0};
     5674        double    slope_magnitude,alpha2,Jdet;
     5675        double    slope[3]={0.0,0.0,0.0};
     5676        double    MAXSLOPE=.06; // 6 %
     5677        double    MOUNTAINKEXPONENT=10;
     5678        double    L[2][numdof];
     5679        double    DL[2][2]={{ 0,0 },{0,0}}; //for basal drag
     5680        double    DL_scalar;
     5681        Friction  *friction = NULL;
     5682        GaussPenta *gauss=NULL;
     5683
     5684        /*Initialize Element matrix and return if necessary*/
     5685        if(IsOnShelf() || !IsOnBed()) return NULL;
     5686
     5687        ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,PattynApproximationEnum);
     5688
     5689        /*Retrieve all inputs and parameters*/
     5690        GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
     5691        for(i=0;i<NUMVERTICES2D;i++) for(j=0;j<2;j++) xyz_list_tria[i][j]=xyz_list[i][j];
     5692        parameters->FindParam(&analysis_type,AnalysisTypeEnum);
     5693        Input* surface_input=inputs->GetInput(SurfaceEnum); _assert_(surface_input);
     5694        Input* vx_input=inputs->GetInput(VxEnum);           _assert_(vx_input);
     5695        Input* vy_input=inputs->GetInput(VyEnum);           _assert_(vy_input);
     5696        Input* vz_input=inputs->GetInput(VzEnum);           _assert_(vz_input);
     5697
     5698        /*build friction object, used later on: */
     5699        friction=new Friction("2d",inputs,matpar,analysis_type);
     5700
     5701        /* Start  looping on the number of gaussian points: */
     5702        gauss=new GaussPenta(0,1,2,2);
     5703        for (ig=gauss->begin();ig<gauss->end();ig++){
     5704
     5705                gauss->GaussPoint(ig);
     5706
     5707                GetTriaJacobianDeterminant(&Jdet, &xyz_list_tria[0][0],gauss);
     5708                GetL(&L[0][0], gauss,NDOF2);
     5709
     5710                surface_input->GetParameterDerivativeValue(&slope[0],&xyz_list[0][0],gauss);
     5711                friction->GetAlpha2(&alpha2, gauss,VxEnum,VyEnum,VzEnum);
     5712                slope_magnitude=sqrt(pow(slope[0],2)+pow(slope[1],2));
     5713
     5714                // If we have a slope > 6% for this element,  it means  we are on a mountain. In this particular case,
     5715                //velocity should be = 0. To achieve this result, we set alpha2_list to a very high value: */
     5716                if (slope_magnitude>MAXSLOPE){
     5717                        alpha2=pow((double)10,MOUNTAINKEXPONENT);
     5718                }
     5719               
     5720                DL_scalar=alpha2*gauss->weight*Jdet;
     5721                for (i=0;i<2;i++) DL[i][i]=DL_scalar;
     5722               
     5723                TripleMultiply( &L[0][0],2,numdof,1,
     5724                                        &DL[0][0],2,2,0,
     5725                                        &L[0][0],2,numdof,0,
     5726                                        &Ke->values[0],1);
     5727        }
     5728
     5729        /*Clean up and return*/
     5730        delete gauss;
     5731        delete friction;
     5732        return Ke;
     5733}
     5734/*}}}*/
     5735/*FUNCTION Penta::CreateKMatrixDiagnosticPattynStokes{{{1*/
     5736ElementMatrix* Penta::CreateKMatrixDiagnosticPattynStokes(void){
     5737
     5738        /*compute all stiffness matrices for this element*/
     5739        ElementMatrix* Ke1=CreateKMatrixDiagnosticPattyn();
     5740        ElementMatrix* Ke2=CreateKMatrixDiagnosticStokes();
     5741        ElementMatrix* Ke3=CreateKMatrixCouplingPattynStokes();
     5742        ElementMatrix* Ke =new ElementMatrix(Ke1,Ke2,Ke3);
     5743
     5744        /*clean-up and return*/
     5745        delete Ke1;
     5746        delete Ke2;
     5747        delete Ke3;
     5748        return Ke;
     5749}
     5750/*}}}*/
     5751/*FUNCTION Penta::CreateKMatrixDiagnosticStokes{{{1*/
     5752ElementMatrix* Penta::CreateKMatrixDiagnosticStokes(void){
     5753
     5754        /*compute all stiffness matrices for this element*/
     5755        ElementMatrix* Ke1=CreateKMatrixDiagnosticStokesViscous();
     5756        ElementMatrix* Ke2=CreateKMatrixDiagnosticStokesFriction();
     5757        ElementMatrix* Ke =new ElementMatrix(Ke1,Ke2);
     5758
     5759        /*clean-up and return*/
     5760        delete Ke1;
     5761        delete Ke2;
     5762        return Ke;
     5763}
     5764/*}}}*/
     5765/*FUNCTION Penta::CreateKMatrixDiagnosticStokesViscous {{{1*/
     5766ElementMatrix* Penta::CreateKMatrixDiagnosticStokesViscous(void){
     5767
     5768        /*Intermediaries */
     5769        int        i,j,ig,approximation;
     5770        double     Jdet,viscosity,stokesreconditioning;
     5771        double     xyz_list[NUMVERTICES][3];
     5772        double     epsilon[6]; /* epsilon=[exx,eyy,ezz,exy,exz,eyz];*/
     5773        double     B[8][27];
     5774        double     B_prime[8][27];
     5775        double     D_scalar;
     5776        double     D[8][8]={0.0};
     5777        double     Ke_temp[27][27]={0.0}; //for the six nodes and the bubble
     5778        double     Ke_gaussian[27][27];
     5779        GaussPenta *gauss=NULL;
     5780
     5781        /*If on water or not Stokes, skip stiffness: */
     5782        inputs->GetParameterValue(&approximation,ApproximationEnum);
     5783        if(approximation!=StokesApproximationEnum && approximation!=MacAyealStokesApproximationEnum && approximation!=PattynStokesApproximationEnum) return NULL;
     5784        ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,StokesApproximationEnum);
     5785
     5786        /*Retrieve all inputs and parameters*/
     5787        GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
     5788        parameters->FindParam(&stokesreconditioning,DiagnosticStokesreconditioningEnum);
     5789        Input* vx_input=inputs->GetInput(VxEnum); _assert_(vx_input);
     5790        Input* vy_input=inputs->GetInput(VyEnum); _assert_(vy_input);
     5791        Input* vz_input=inputs->GetInput(VzEnum); _assert_(vz_input);
     5792
     5793        /* Start  looping on the number of gaussian points: */
     5794        gauss=new GaussPenta(5,5);
     5795        for (ig=gauss->begin();ig<gauss->end();ig++){
     5796
     5797                gauss->GaussPoint(ig);
     5798
     5799                GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss);
     5800                GetBStokes(&B[0][0],&xyz_list[0][0],gauss);
     5801                GetBprimeStokes(&B_prime[0][0],&xyz_list[0][0],gauss);
     5802
     5803                this->GetStrainRate3d(&epsilon[0],&xyz_list[0][0],gauss,vx_input,vy_input,vz_input);
     5804                matice->GetViscosity3dStokes(&viscosity,&epsilon[0]);
     5805
     5806                D_scalar=gauss->weight*Jdet;
     5807                for (i=0;i<6;i++) D[i][i]=D_scalar*2*viscosity;
     5808                for (i=6;i<8;i++) D[i][i]=-D_scalar*stokesreconditioning;
     5809
     5810                TripleMultiply( &B[0][0],8,27,1,
     5811                                        &D[0][0],8,8,0,
     5812                                        &B_prime[0][0],8,27,0,
     5813                                        &Ke_gaussian[0][0],0);
     5814
     5815                for(i=0;i<27;i++) for(j=0;j<27;j++) Ke_temp[i][j]+=Ke_gaussian[i][j];
     5816        }
     5817
     5818        /*Condensation*/
     5819        ReduceMatrixStokes(Ke->values, &Ke_temp[0][0]);
     5820
     5821        /*Clean up and return*/
     5822        delete gauss;
     5823        return Ke;
     5824}
     5825/*}}}*/
     5826/*FUNCTION Penta::CreateKMatrixDiagnosticStokesFriction {{{1*/
     5827ElementMatrix* Penta::CreateKMatrixDiagnosticStokesFriction(void){
     5828
     5829        /*Constants*/
     5830        const int numdof=NUMVERTICES*NDOF4;
     5831        const int numdof2d=NUMVERTICES2D*NDOF4;
     5832
     5833        /*Intermediaries */
     5834        int        i,j,ig;
     5835        int        analysis_type,approximation;
     5836        double     stokesreconditioning;
     5837        double     viscosity,alpha2_gauss,Jdet2d;
     5838        double    bed_normal[3];
     5839        double     epsilon[6]; /* epsilon=[exx,eyy,ezz,exy,exz,eyz];*/
     5840        double     xyz_list[NUMVERTICES][3];
     5841        double    xyz_list_tria[NUMVERTICES2D][3];
     5842        double     LStokes[14][numdof2d];
     5843        double     LprimeStokes[14][numdof2d];
     5844        double     DLStokes[14][14]={0.0};
     5845        double     Ke_drag_gaussian[numdof2d][numdof2d];
     5846        Friction*  friction=NULL;
     5847        GaussPenta *gauss=NULL;
     5848
     5849        /*If on water or not Stokes, skip stiffness: */
     5850        inputs->GetParameterValue(&approximation,ApproximationEnum);
     5851        if(IsOnShelf() || !IsOnBed() || (approximation!=StokesApproximationEnum && approximation!=MacAyealStokesApproximationEnum &&  approximation!=PattynStokesApproximationEnum)) return NULL;
     5852        ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,StokesApproximationEnum);
     5853
     5854        /*Retrieve all inputs and parameters*/
     5855        GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
     5856        parameters->FindParam(&analysis_type,AnalysisTypeEnum);
     5857        parameters->FindParam(&stokesreconditioning,DiagnosticStokesreconditioningEnum);
     5858        Input* vx_input=inputs->GetInput(VxEnum); _assert_(vx_input);
     5859        Input* vy_input=inputs->GetInput(VyEnum); _assert_(vy_input);
     5860        Input* vz_input=inputs->GetInput(VzEnum); _assert_(vz_input);
     5861        for(i=0;i<NUMVERTICES2D;i++) for(j=0;j<3;j++) xyz_list_tria[i][j]=xyz_list[i][j];
     5862
     5863        /*build friction object, used later on: */
     5864        friction=new Friction("3d",inputs,matpar,analysis_type);
     5865
     5866        /* Start  looping on the number of gaussian points: */
     5867        gauss=new GaussPenta(0,1,2,2);
     5868        for (ig=gauss->begin();ig<gauss->end();ig++){
     5869
     5870                gauss->GaussPoint(ig);
     5871
     5872                GetTriaJacobianDeterminant(&Jdet2d, &xyz_list_tria[0][0],gauss);
     5873                GetLStokes(&LStokes[0][0], gauss);
     5874                GetLprimeStokes(&LprimeStokes[0][0], &xyz_list[0][0], gauss);
     5875
     5876                this->GetStrainRate3d(&epsilon[0],&xyz_list[0][0],gauss,vx_input,vy_input,vz_input);
     5877                matice->GetViscosity3dStokes(&viscosity,&epsilon[0]);
     5878
     5879                BedNormal(&bed_normal[0],xyz_list_tria);
     5880                friction->GetAlpha2(&alpha2_gauss, gauss,VxEnum,VyEnum,VzEnum);
     5881
     5882                DLStokes[0][0]=alpha2_gauss*gauss->weight*Jdet2d;
     5883                DLStokes[1][1]=alpha2_gauss*gauss->weight*Jdet2d;
     5884                DLStokes[2][2]=-alpha2_gauss*gauss->weight*Jdet2d*bed_normal[0]*bed_normal[2];
     5885                DLStokes[3][3]=-alpha2_gauss*gauss->weight*Jdet2d*bed_normal[1]*bed_normal[2];
     5886                DLStokes[4][4]=-alpha2_gauss*gauss->weight*Jdet2d*bed_normal[0]*bed_normal[2];
     5887                DLStokes[5][5]=-alpha2_gauss*gauss->weight*Jdet2d*bed_normal[1]*bed_normal[2];
     5888                DLStokes[6][6]=-2*viscosity*gauss->weight*Jdet2d*bed_normal[0];
     5889                DLStokes[7][7]=-2*viscosity*gauss->weight*Jdet2d*bed_normal[1];
     5890                DLStokes[8][8]=-2*viscosity*gauss->weight*Jdet2d*bed_normal[2];
     5891                DLStokes[9][9]=-2*viscosity*gauss->weight*Jdet2d*bed_normal[0]/2.0;
     5892                DLStokes[10][10]=-2*viscosity*gauss->weight*Jdet2d*bed_normal[1]/2.0;
     5893                DLStokes[11][11]=stokesreconditioning*gauss->weight*Jdet2d*bed_normal[0];
     5894                DLStokes[12][12]=stokesreconditioning*gauss->weight*Jdet2d*bed_normal[1];
     5895                DLStokes[13][13]=stokesreconditioning*gauss->weight*Jdet2d*bed_normal[2];
     5896
     5897                TripleMultiply( &LStokes[0][0],14,numdof2d,1,
     5898                                        &DLStokes[0][0],14,14,0,
     5899                                        &LprimeStokes[0][0],14,numdof2d,0,
     5900                                        &Ke_drag_gaussian[0][0],0);
     5901
     5902                for(i=0;i<numdof2d;i++) for(j=0;j<numdof2d;j++) Ke->values[i*numdof+j]+=Ke_drag_gaussian[i][j];
     5903        }
     5904
     5905        /*Clean up and return*/
     5906        delete gauss;
     5907        delete friction;
     5908        return Ke;
     5909}
     5910/*}}}*/
     5911/*FUNCTION Penta::CreateKMatrixDiagnosticVert {{{1*/
     5912ElementMatrix* Penta::CreateKMatrixDiagnosticVert(void){
     5913       
     5914        /*compute all stiffness matrices for this element*/
     5915        ElementMatrix* Ke1=CreateKMatrixDiagnosticVertVolume();
     5916        ElementMatrix* Ke2=CreateKMatrixDiagnosticVertSurface();
     5917        ElementMatrix* Ke =new ElementMatrix(Ke1,Ke2);
     5918
     5919        /*clean-up and return*/
     5920        delete Ke1;
     5921        delete Ke2;
     5922        return Ke;
     5923
     5924}
     5925/*}}}*/
     5926/*FUNCTION Penta::CreateKMatrixDiagnosticVertVolume {{{1*/
     5927ElementMatrix* Penta::CreateKMatrixDiagnosticVertVolume(void){
     5928
     5929        /*Constants*/
     5930        const int    numdof=NDOF1*NUMVERTICES;
     5931
     5932        /*Intermediaries */
     5933        int         i,j,ig;
     5934        double      Jdet;
     5935        double      xyz_list[NUMVERTICES][3];
     5936        double      B[NDOF1][NUMVERTICES];
     5937        double      Bprime[NDOF1][NUMVERTICES];
     5938        double      DL_scalar;
     5939        GaussPenta  *gauss=NULL;
     5940
     5941        /*Initialize Element matrix*/
     5942        ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,NoneApproximationEnum);
     5943
     5944        /*Retrieve all inputs and parameters*/
     5945        GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
     5946
     5947        /* Start  looping on the number of gaussian points: */
     5948        gauss=new GaussPenta(2,2);
     5949        for (ig=gauss->begin();ig<gauss->end();ig++){
     5950
     5951                gauss->GaussPoint(ig);
     5952
     5953                GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss);
     5954                GetBVert(&B[0][0], &xyz_list[0][0], gauss);
     5955                GetBprimeVert(&Bprime[0][0], &xyz_list[0][0], gauss);
     5956
     5957                DL_scalar=gauss->weight*Jdet;
     5958
     5959                TripleMultiply( &B[0][0],1,NUMVERTICES,1,
     5960                                        &DL_scalar,1,1,0,
     5961                                        &Bprime[0][0],1,NUMVERTICES,0,
     5962                                        &Ke->values[0],1);
     5963        }
     5964
     5965        /*Clean up and return*/
     5966        delete gauss;
     5967        return Ke;
     5968}
     5969/*}}}*/
     5970/*FUNCTION Penta::CreateKMatrixDiagnosticVertSurface {{{1*/
     5971ElementMatrix* Penta::CreateKMatrixDiagnosticVertSurface(void){
     5972
     5973        if (!IsOnSurface()) return NULL;
     5974
     5975        /*Constants*/
     5976        const int numdof=NDOF1*NUMVERTICES;
     5977
     5978        /*Intermediaries */
     5979        int       i,j,ig;
     5980        double    xyz_list[NUMVERTICES][3];
     5981        double    xyz_list_tria[NUMVERTICES2D][3];
     5982        double    surface_normal[3];
     5983        double    Jdet2d,DL_scalar;
     5984        double    basis[NUMVERTICES];
     5985        GaussPenta *gauss=NULL;
     5986
     5987        /*Initialize Element matrix*/
     5988        ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,NoneApproximationEnum);
     5989
     5990        /*Retrieve all inputs and parameters*/
     5991        GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
     5992        for(i=0;i<NUMVERTICES2D;i++) for(j=0;j<3;j++) xyz_list_tria[i][j]=xyz_list[i+3][j];
     5993        SurfaceNormal(&surface_normal[0],xyz_list_tria);
     5994
     5995        /* Start  looping on the number of gaussian points: */
     5996        gauss=new GaussPenta(3,4,5,2);
     5997        for (ig=gauss->begin();ig<gauss->end();ig++){
     5998
     5999                gauss->GaussPoint(ig);
     6000
     6001                GetTriaJacobianDeterminant(&Jdet2d, &xyz_list_tria[0][0],gauss);
     6002                GetNodalFunctionsP1(&basis[0], gauss);
     6003
     6004                DL_scalar= - gauss->weight*Jdet2d*surface_normal[2];
     6005
     6006                TripleMultiply( basis,1,numdof,1,
     6007                                        &DL_scalar,1,1,0,
     6008                                        basis,1,numdof,0,
     6009                                        &Ke->values[0],1);
     6010        }
     6011
     6012        /*Clean up and return*/
     6013        delete gauss;
     6014        return Ke;
     6015}
     6016/*}}}*/
     6017/*FUNCTION Penta::CreatePVectorCouplingMacAyealStokes {{{1*/
     6018ElementVector* Penta::CreatePVectorCouplingMacAyealStokes(void){
     6019
     6020        /*compute all load vectors for this element*/
     6021        ElementVector* pe1=CreatePVectorCouplingMacAyealStokesViscous();
     6022        ElementVector* pe2=CreatePVectorCouplingMacAyealStokesFriction();
     6023        ElementVector* pe =new ElementVector(pe1,pe2);
     6024
     6025        /*clean-up and return*/
     6026        delete pe1;
     6027        delete pe2;
     6028        return pe;
     6029}
     6030/*}}}*/
     6031/*FUNCTION Penta::CreatePVectorCouplingMacAyealStokesViscous {{{1*/
     6032ElementVector* Penta::CreatePVectorCouplingMacAyealStokesViscous(void){
     6033
     6034        /*Constants*/
     6035        const int   numdof=NUMVERTICES*NDOF4;
     6036
     6037        /*Intermediaries */
     6038        int         i,j,ig;
     6039        int         approximation;
     6040        double      viscosity,Jdet;
     6041        double      stokesreconditioning;
     6042        double      epsilon[6]; /* epsilon=[exx,eyy,ezz,exy,exz,eyz];*/
     6043        double      dw[3];
     6044        double      xyz_list[NUMVERTICES][3];
     6045        double      basis[6]; //for the six nodes of the penta
     6046        double      dbasis[3][6]; //for the six nodes of the penta
     6047        GaussPenta *gauss=NULL;
     6048
     6049        /*Initialize Element vector and return if necessary*/
     6050        inputs->GetParameterValue(&approximation,ApproximationEnum);
     6051        if(approximation!=MacAyealStokesApproximationEnum) return NULL;
     6052        ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters,StokesApproximationEnum);
     6053
     6054        /*Retrieve all inputs and parameters*/
     6055        GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
     6056        this->parameters->FindParam(&stokesreconditioning,DiagnosticStokesreconditioningEnum);
     6057        Input* vx_input=inputs->GetInput(VxEnum);               _assert_(vx_input);
     6058        Input* vy_input=inputs->GetInput(VyEnum);               _assert_(vy_input);
     6059        Input* vz_input=inputs->GetInput(VzEnum);               _assert_(vz_input);
     6060        Input* vzmacayeal_input=inputs->GetInput(VzMacAyealEnum);   _assert_(vzmacayeal_input);
     6061
     6062        /* Start  looping on the number of gaussian points: */
     6063        gauss=new GaussPenta(5,5);
     6064        for (ig=gauss->begin();ig<gauss->end();ig++){
     6065
     6066                gauss->GaussPoint(ig);
     6067
     6068                GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss);
     6069                GetNodalFunctionsP1(&basis[0], gauss);
     6070                GetNodalFunctionsP1Derivatives(&dbasis[0][0],&xyz_list[0][0], gauss);
     6071
     6072                vzmacayeal_input->GetParameterDerivativeValue(&dw[0],&xyz_list[0][0],gauss);
     6073
     6074                this->GetStrainRate3d(&epsilon[0],&xyz_list[0][0],gauss,vx_input,vy_input,vz_input);
     6075                matice->GetViscosity3dStokes(&viscosity,&epsilon[0]);
     6076
     6077                for(i=0;i<NUMVERTICES;i++){
     6078                        pe->values[i*NDOF4+0]+=-Jdet*gauss->weight*viscosity*dw[0]*dbasis[2][i];
     6079                        pe->values[i*NDOF4+1]+=-Jdet*gauss->weight*viscosity*dw[1]*dbasis[2][i];
     6080                        pe->values[i*NDOF4+2]+=-Jdet*gauss->weight*viscosity*(dw[0]*dbasis[0][i]+dw[1]*dbasis[1][i]+2*dw[2]*dbasis[2][i]);
     6081                        pe->values[i*NDOF4+3]+=Jdet*gauss->weight*stokesreconditioning*dw[2]*basis[i];
     6082                }
     6083        }
     6084
     6085        /*Clean up and return*/
     6086        delete gauss;
     6087        return pe;
     6088}
     6089/*}}}*/
     6090/*FUNCTION Penta::CreatePVectorCouplingMacAyealStokesFriction{{{1*/
     6091ElementVector* Penta::CreatePVectorCouplingMacAyealStokesFriction(void){
     6092
     6093        /*Constants*/
     6094        const int numdof=NUMVERTICES*NDOF4;
     6095
     6096        /*Intermediaries*/
     6097        int         i,j,ig;
     6098        int         approximation,analysis_type;
     6099        double      Jdet,Jdet2d;
     6100        double      stokesreconditioning;
     6101        double     bed_normal[3];
     6102        double      epsilon[6]; /* epsilon=[exx,eyy,ezz,exy,exz,eyz];*/
     6103        double      viscosity, w, alpha2_gauss;
     6104        double      dw[3];
     6105        double     xyz_list_tria[NUMVERTICES2D][3];
     6106        double      xyz_list[NUMVERTICES][3];
     6107        double      basis[6]; //for the six nodes of the penta
     6108        Tria*       tria=NULL;
     6109        Friction*   friction=NULL;
     6110        GaussPenta  *gauss=NULL;
     6111
     6112        /*Initialize Element vector and return if necessary*/
     6113        if(!IsOnBed() || IsOnShelf()) return NULL;
     6114        inputs->GetParameterValue(&approximation,ApproximationEnum);
     6115        if(approximation!=MacAyealStokesApproximationEnum) return NULL;
     6116        ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters,StokesApproximationEnum);
     6117
     6118        /*Retrieve all inputs and parameters*/
     6119        GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
     6120        parameters->FindParam(&analysis_type,AnalysisTypeEnum);
     6121        this->parameters->FindParam(&stokesreconditioning,DiagnosticStokesreconditioningEnum);
     6122        Input* vx_input=inputs->GetInput(VxEnum);               _assert_(vx_input);
     6123        Input* vy_input=inputs->GetInput(VyEnum);               _assert_(vy_input);
     6124        Input* vz_input=inputs->GetInput(VzEnum);               _assert_(vz_input);
     6125        Input* vzmacayeal_input=inputs->GetInput(VzMacAyealEnum);   _assert_(vzmacayeal_input);
     6126
     6127        for(i=0;i<NUMVERTICES2D;i++) for(j=0;j<3;j++) xyz_list_tria[i][j]=xyz_list[i][j];
     6128
     6129        /*build friction object, used later on: */
     6130        friction=new Friction("3d",inputs,matpar,analysis_type);
     6131
     6132        /* Start looping on the number of gauss 2d (nodes on the bedrock) */
     6133        gauss=new GaussPenta(0,1,2,2);
     6134        for(ig=gauss->begin();ig<gauss->end();ig++){
     6135
     6136                gauss->GaussPoint(ig);
     6137
     6138                GetTriaJacobianDeterminant(&Jdet2d, &xyz_list_tria[0][0], gauss);
     6139                GetNodalFunctionsP1(basis, gauss);
     6140
     6141                vzmacayeal_input->GetParameterValue(&w, gauss);
     6142                vzmacayeal_input->GetParameterDerivativeValue(&dw[0],&xyz_list[0][0],gauss);
     6143
     6144                BedNormal(&bed_normal[0],xyz_list_tria);
     6145                this->GetStrainRate3d(&epsilon[0],&xyz_list[0][0],gauss,vx_input,vy_input,vz_input);
     6146                matice->GetViscosity3dStokes(&viscosity,&epsilon[0]);
     6147                friction->GetAlpha2(&alpha2_gauss, gauss,VxEnum,VyEnum,VzEnum);
     6148
     6149                for(i=0;i<NUMVERTICES2D;i++){
     6150                        pe->values[i*NDOF4+0]+=Jdet2d*gauss->weight*(alpha2_gauss*w*bed_normal[0]*bed_normal[2]+2*viscosity*dw[2]*bed_normal[0])*basis[i];
     6151                        pe->values[i*NDOF4+1]+=Jdet2d*gauss->weight*(alpha2_gauss*w*bed_normal[1]*bed_normal[2]+2*viscosity*dw[2]*bed_normal[1])*basis[i];
     6152                        pe->values[i*NDOF4+2]+=Jdet2d*gauss->weight*2*viscosity*(dw[0]*bed_normal[0]+dw[1]*bed_normal[1]+dw[2]*bed_normal[2])*basis[i];
     6153                }
     6154        }
     6155
     6156        /*Clean up and return*/
     6157        delete gauss;
     6158        delete friction;
     6159        return pe;
     6160}
     6161/*}}}*/
     6162/*FUNCTION Penta::CreatePVectorCouplingPattynStokes {{{1*/
     6163ElementVector* Penta::CreatePVectorCouplingPattynStokes(void){
     6164
     6165        /*compute all load vectors for this element*/
     6166        ElementVector* pe1=CreatePVectorCouplingPattynStokesViscous();
     6167        ElementVector* pe2=CreatePVectorCouplingPattynStokesFriction();
     6168        ElementVector* pe =new ElementVector(pe1,pe2);
     6169
     6170        /*clean-up and return*/
     6171        delete pe1;
     6172        delete pe2;
     6173        return pe;
     6174}
     6175/*}}}*/
     6176/*FUNCTION Penta::CreatePVectorCouplingPattynStokesViscous {{{1*/
     6177ElementVector* Penta::CreatePVectorCouplingPattynStokesViscous(void){
     6178
     6179        /*Constants*/
     6180        const int   numdof=NUMVERTICES*NDOF4;
     6181
     6182        /*Intermediaries */
     6183        int         i,j,ig;
     6184        int         approximation;
     6185        double      viscosity,Jdet;
     6186        double      stokesreconditioning;
     6187        double      epsilon[6]; /* epsilon=[exx,eyy,ezz,exy,exz,eyz];*/
     6188        double      dw[3];
     6189        double      xyz_list[NUMVERTICES][3];
     6190        double      basis[6]; //for the six nodes of the penta
     6191        double      dbasis[3][6]; //for the six nodes of the penta
     6192        GaussPenta *gauss=NULL;
     6193
     6194        /*Initialize Element vector and return if necessary*/
     6195        inputs->GetParameterValue(&approximation,ApproximationEnum);
     6196        if(approximation!=PattynStokesApproximationEnum) return NULL;
     6197        ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters,StokesApproximationEnum);
     6198
     6199        /*Retrieve all inputs and parameters*/
     6200        GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
     6201        this->parameters->FindParam(&stokesreconditioning,DiagnosticStokesreconditioningEnum);
     6202        Input* vx_input=inputs->GetInput(VxEnum);               _assert_(vx_input);
     6203        Input* vy_input=inputs->GetInput(VyEnum);               _assert_(vy_input);
     6204        Input* vz_input=inputs->GetInput(VzEnum);               _assert_(vz_input);
     6205        Input* vzpattyn_input=inputs->GetInput(VzPattynEnum);   _assert_(vzpattyn_input);
     6206
     6207        /* Start  looping on the number of gaussian points: */
     6208        gauss=new GaussPenta(5,5);
     6209        for (ig=gauss->begin();ig<gauss->end();ig++){
     6210
     6211                gauss->GaussPoint(ig);
     6212
     6213                GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss);
     6214                GetNodalFunctionsP1(&basis[0], gauss);
     6215                GetNodalFunctionsP1Derivatives(&dbasis[0][0],&xyz_list[0][0], gauss);
     6216
     6217                vzpattyn_input->GetParameterDerivativeValue(&dw[0],&xyz_list[0][0],gauss);
     6218
     6219                this->GetStrainRate3d(&epsilon[0],&xyz_list[0][0],gauss,vx_input,vy_input,vz_input);
     6220                matice->GetViscosity3dStokes(&viscosity,&epsilon[0]);
     6221
     6222                for(i=0;i<NUMVERTICES;i++){
     6223                        pe->values[i*NDOF4+0]+=-Jdet*gauss->weight*viscosity*dw[0]*dbasis[2][i];
     6224                        pe->values[i*NDOF4+1]+=-Jdet*gauss->weight*viscosity*dw[1]*dbasis[2][i];
     6225                        pe->values[i*NDOF4+2]+=-Jdet*gauss->weight*viscosity*(dw[0]*dbasis[0][i]+dw[1]*dbasis[1][i]+2*dw[2]*dbasis[2][i]);
     6226                        pe->values[i*NDOF4+3]+=Jdet*gauss->weight*stokesreconditioning*dw[2]*basis[i];
     6227                }
     6228        }
     6229
     6230        /*Clean up and return*/
     6231        delete gauss;
     6232        return pe;
     6233}
     6234/*}}}*/
     6235/*FUNCTION Penta::CreatePVectorCouplingPattynStokesFriction{{{1*/
     6236ElementVector* Penta::CreatePVectorCouplingPattynStokesFriction(void){
     6237
     6238        /*Constants*/
     6239        const int numdof=NUMVERTICES*NDOF4;
     6240
     6241        /*Intermediaries*/
     6242        int         i,j,ig;
     6243        int         approximation,analysis_type;
     6244        double      Jdet,Jdet2d;
     6245        double      stokesreconditioning;
     6246        double     bed_normal[3];
     6247        double      epsilon[6]; /* epsilon=[exx,eyy,ezz,exy,exz,eyz];*/
     6248        double      viscosity, w, alpha2_gauss;
     6249        double      dw[3];
     6250        double     xyz_list_tria[NUMVERTICES2D][3];
     6251        double      xyz_list[NUMVERTICES][3];
     6252        double      basis[6]; //for the six nodes of the penta
     6253        Tria*       tria=NULL;
     6254        Friction*   friction=NULL;
     6255        GaussPenta  *gauss=NULL;
     6256
     6257        /*Initialize Element vector and return if necessary*/
     6258        if(!IsOnBed() || IsOnShelf()) return NULL;
     6259        inputs->GetParameterValue(&approximation,ApproximationEnum);
     6260        if(approximation!=PattynStokesApproximationEnum) return NULL;
     6261        ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters,StokesApproximationEnum);
     6262
     6263        /*Retrieve all inputs and parameters*/
     6264        GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
     6265        parameters->FindParam(&analysis_type,AnalysisTypeEnum);
     6266        this->parameters->FindParam(&stokesreconditioning,DiagnosticStokesreconditioningEnum);
     6267        Input* vx_input=inputs->GetInput(VxEnum);               _assert_(vx_input);
     6268        Input* vy_input=inputs->GetInput(VyEnum);               _assert_(vy_input);
     6269        Input* vz_input=inputs->GetInput(VzEnum);               _assert_(vz_input);
     6270        Input* vzpattyn_input=inputs->GetInput(VzPattynEnum);   _assert_(vzpattyn_input);
     6271
     6272        for(i=0;i<NUMVERTICES2D;i++) for(j=0;j<3;j++) xyz_list_tria[i][j]=xyz_list[i][j];
     6273
     6274        /*build friction object, used later on: */
     6275        friction=new Friction("3d",inputs,matpar,analysis_type);
     6276
     6277        /* Start looping on the number of gauss 2d (nodes on the bedrock) */
     6278        gauss=new GaussPenta(0,1,2,2);
     6279        for(ig=gauss->begin();ig<gauss->end();ig++){
     6280
     6281                gauss->GaussPoint(ig);
     6282
     6283                GetTriaJacobianDeterminant(&Jdet2d, &xyz_list_tria[0][0], gauss);
     6284                GetNodalFunctionsP1(basis, gauss);
     6285
     6286                vzpattyn_input->GetParameterValue(&w, gauss);
     6287                vzpattyn_input->GetParameterDerivativeValue(&dw[0],&xyz_list[0][0],gauss);
     6288
     6289                BedNormal(&bed_normal[0],xyz_list_tria);
     6290                this->GetStrainRate3d(&epsilon[0],&xyz_list[0][0],gauss,vx_input,vy_input,vz_input);
     6291                matice->GetViscosity3dStokes(&viscosity,&epsilon[0]);
     6292                friction->GetAlpha2(&alpha2_gauss, gauss,VxEnum,VyEnum,VzEnum);
     6293
     6294                for(i=0;i<NUMVERTICES2D;i++){
     6295                        pe->values[i*NDOF4+0]+=Jdet2d*gauss->weight*(alpha2_gauss*w*bed_normal[0]*bed_normal[2]+2*viscosity*dw[2]*bed_normal[0])*basis[i];
     6296                        pe->values[i*NDOF4+1]+=Jdet2d*gauss->weight*(alpha2_gauss*w*bed_normal[1]*bed_normal[2]+2*viscosity*dw[2]*bed_normal[1])*basis[i];
     6297                        pe->values[i*NDOF4+2]+=Jdet2d*gauss->weight*2*viscosity*(dw[0]*bed_normal[0]+dw[1]*bed_normal[1]+dw[2]*bed_normal[2])*basis[i];
     6298                }
     6299        }
     6300
     6301        /*Clean up and return*/
     6302        delete gauss;
     6303        delete friction;
     6304        return pe;
     6305}
     6306/*}}}*/
     6307/*FUNCTION Penta::CreatePVectorDiagnosticHoriz{{{1*/
     6308ElementVector* Penta::CreatePVectorDiagnosticHoriz(void){
     6309
     6310        int approximation;
     6311        inputs->GetParameterValue(&approximation,ApproximationEnum);
     6312
     6313        switch(approximation){
     6314                case MacAyealApproximationEnum:
     6315                        return CreatePVectorDiagnosticMacAyeal();
     6316                case PattynApproximationEnum:
     6317                        return CreatePVectorDiagnosticPattyn();
     6318                case HutterApproximationEnum:
     6319                        return NULL;
     6320                case NoneApproximationEnum:
     6321                        return NULL;
     6322                case StokesApproximationEnum:
     6323                        return CreatePVectorDiagnosticStokes();
     6324                case MacAyealPattynApproximationEnum:
     6325                        return CreatePVectorDiagnosticMacAyealPattyn();
     6326                case MacAyealStokesApproximationEnum:
     6327                        return CreatePVectorDiagnosticMacAyealStokes();
     6328                case PattynStokesApproximationEnum:
     6329                        return CreatePVectorDiagnosticPattynStokes();
     6330                default:
     6331                        _error_("Approximation %s not supported yet",EnumToStringx(approximation));
     6332        }
     6333}
     6334/*}}}*/
     6335/*FUNCTION Penta::CreatePVectorDiagnosticMacAyealPattyn{{{1*/
     6336ElementVector* Penta::CreatePVectorDiagnosticMacAyealPattyn(void){
     6337
     6338        /*compute all load vectors for this element*/
     6339        ElementVector* pe1=CreatePVectorDiagnosticMacAyeal();
     6340        ElementVector* pe2=CreatePVectorDiagnosticPattyn();
     6341        ElementVector* pe =new ElementVector(pe1,pe2);
     6342
     6343        /*clean-up and return*/
     6344        delete pe1;
     6345        delete pe2;
     6346        return pe;
     6347}
     6348/*}}}*/
     6349/*FUNCTION Penta::CreatePVectorDiagnosticMacAyealStokes{{{1*/
     6350ElementVector* Penta::CreatePVectorDiagnosticMacAyealStokes(void){
     6351
     6352        /*compute all load vectors for this element*/
     6353        ElementVector* pe1=CreatePVectorDiagnosticMacAyeal();
     6354        ElementVector* pe2=CreatePVectorDiagnosticStokes();
     6355        ElementVector* pe3=CreatePVectorCouplingMacAyealStokes();
     6356        ElementVector* pe =new ElementVector(pe1,pe2,pe3);
     6357
     6358        /*clean-up and return*/
     6359        delete pe1;
     6360        delete pe2;
     6361        delete pe3;
     6362        return pe;
     6363}
     6364/*}}}*/
     6365/*FUNCTION Penta::CreatePVectorDiagnosticPattynStokes{{{1*/
     6366ElementVector* Penta::CreatePVectorDiagnosticPattynStokes(void){
     6367
     6368        /*compute all load vectors for this element*/
     6369        ElementVector* pe1=CreatePVectorDiagnosticPattyn();
     6370        ElementVector* pe2=CreatePVectorDiagnosticStokes();
     6371        ElementVector* pe3=CreatePVectorCouplingPattynStokes();
     6372        ElementVector* pe =new ElementVector(pe1,pe2,pe3);
     6373
     6374        /*clean-up and return*/
     6375        delete pe1;
     6376        delete pe2;
     6377        delete pe3;
     6378        return pe;
     6379}
     6380/*}}}*/
     6381/*FUNCTION Penta::CreatePVectorDiagnosticHutter{{{1*/
     6382ElementVector* Penta::CreatePVectorDiagnosticHutter(void){
     6383
     6384        /*Constants*/
     6385        const int numdofs=NDOF2*NUMVERTICES;
     6386
     6387        /*Intermediaries*/
     6388        int          i,j,k,ig;
     6389        int          node0,node1;
     6390        int          connectivity[2];
     6391        double       Jdet;
     6392        double       xyz_list[NUMVERTICES][3];
     6393        double       xyz_list_segment[2][3];
     6394        double       z_list[NUMVERTICES];
     6395        double       z_segment[2],slope[2];
     6396        double       slope2,constant_part;
     6397        double       rho_ice,gravity,n,B;
     6398        double       ub,vb,z_g,surface,thickness;
     6399        GaussPenta*  gauss=NULL;
     6400
     6401        /*Initialize Element vector*/
     6402        ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters);
     6403
     6404        /*Retrieve all inputs and parameters*/
     6405        GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
     6406        rho_ice=matpar->GetRhoIce();
     6407        gravity=matpar->GetG();
     6408        n=matice->GetN();
     6409        B=matice->GetB();
     6410        Input* thickness_input=inputs->GetInput(ThicknessEnum);  _assert_(thickness_input);
     6411        Input* surface_input=inputs->GetInput(SurfaceEnum);      _assert_(surface_input);
     6412        Input* slopex_input=inputs->GetInput(SurfaceSlopeXEnum); _assert_(slopex_input);
     6413        Input* slopey_input=inputs->GetInput(SurfaceSlopeYEnum); _assert_(slopey_input);
     6414        for(i=0;i<NUMVERTICES;i++)z_list[i]=xyz_list[i][2];
     6415
     6416        /*Loop on the three segments*/
     6417        for(i=0;i<3;i++){
     6418                node0=i;
     6419                node1=i+3;
     6420
     6421                for(j=0;j<3;j++){
     6422                        xyz_list_segment[0][j]=xyz_list[node0][j];
     6423                        xyz_list_segment[1][j]=xyz_list[node1][j];
     6424                }
     6425
     6426                connectivity[0]=nodes[node0]->GetConnectivity();
     6427                connectivity[1]=nodes[node1]->GetConnectivity();
     6428
     6429                /*Loop on the Gauss points: */
     6430                gauss=new GaussPenta(node0,node1,3);
     6431                for(ig=gauss->begin();ig<gauss->end();ig++){
     6432                        gauss->GaussPoint(ig);
     6433
     6434                        slopex_input->GetParameterValue(&slope[0],gauss);
     6435                        slopey_input->GetParameterValue(&slope[1],gauss);
     6436                        surface_input->GetParameterValue(&surface,gauss);
     6437                        thickness_input->GetParameterValue(&thickness,gauss);
     6438
     6439                        slope2=pow(slope[0],2)+pow(slope[1],2);
     6440                        constant_part=-2*pow(rho_ice*gravity,n)*pow(slope2,((n-1)/2));
     6441
     6442                        PentaRef::GetParameterValue(&z_g,&z_list[0],gauss);
     6443                        GetSegmentJacobianDeterminant(&Jdet,&xyz_list_segment[0][0],gauss);
     6444
     6445                        if (IsOnSurface()){
     6446                                for(j=0;j<NDOF2;j++) pe->values[2*node1+j]+=constant_part*pow((surface-z_g)/B,n)*slope[j]*Jdet*gauss->weight/(double)connectivity[1];
     6447                        }
     6448                        else{//connectivity is too large, should take only half on it
     6449                                for(j=0;j<NDOF2;j++) pe->values[2*node1+j]+=constant_part*pow((surface-z_g)/B,n)*slope[j]*Jdet*gauss->weight*2/(double)connectivity[1];
     6450                        }
     6451                }
     6452                delete gauss;
     6453
     6454                //Deal with lower surface
     6455                if (IsOnBed()){
     6456                        constant_part=-1.58*pow((double)10.0,-(double)10.0)*rho_ice*gravity*thickness;
     6457                        ub=constant_part*slope[0];
     6458                        vb=constant_part*slope[1];
     6459
     6460                        pe->values[2*node0]+=ub/(double)connectivity[0];
     6461                        pe->values[2*node0+1]+=vb/(double)connectivity[0];
     6462                }
     6463        }
     6464
     6465        /*Clean up and return*/
     6466        return pe;
     6467}
     6468/*}}}*/
     6469/*FUNCTION Penta::CreatePVectorDiagnosticMacAyeal{{{1*/
     6470ElementVector* Penta::CreatePVectorDiagnosticMacAyeal(void){
     6471
     6472        if (!IsOnBed()) return NULL;
     6473
     6474        /*Call Tria function*/
     6475        Tria* tria=(Tria*)SpawnTria(0,1,2); //nodes 0, 1 and 2 make the new tria.
     6476        ElementVector* pe=tria->CreatePVectorDiagnosticMacAyeal();
     6477        delete tria->matice; delete tria;
     6478
     6479        /*Clean up and return*/
     6480        return pe;
     6481}
     6482/*}}}*/
     6483/*FUNCTION Penta::CreatePVectorDiagnosticPattyn{{{1*/
     6484ElementVector* Penta::CreatePVectorDiagnosticPattyn(void){
     6485
     6486        /*Constants*/
     6487        const int    numdof=NDOF2*NUMVERTICES;
     6488
     6489        /*Intermediaries*/
     6490        int         i,j,ig;
     6491        double      Jdet;
     6492        double      slope[3]; //do not put 2! this goes into GetParameterDerivativeValue, which addresses slope[3] also!
     6493        double      driving_stress_baseline,thickness;
     6494        double      xyz_list[NUMVERTICES][3];
     6495        double      basis[6];
     6496        GaussPenta  *gauss=NULL;
     6497
     6498        /*Initialize Element vector*/
     6499        ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters,PattynApproximationEnum);
     6500
     6501        /*Retrieve all inputs and parameters*/
     6502        GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
     6503        Input* thickness_input=inputs->GetInput(ThicknessEnum); _assert_(thickness_input);
     6504        Input* surface_input=inputs->GetInput(SurfaceEnum);     _assert_(surface_input);
     6505
     6506        /* Start  looping on the number of gaussian points: */
     6507        gauss=new GaussPenta(2,3);
     6508        for (ig=gauss->begin();ig<gauss->end();ig++){
     6509
     6510                gauss->GaussPoint(ig);
     6511
     6512                GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss);
     6513                GetNodalFunctionsP1(basis, gauss);
     6514
     6515                thickness_input->GetParameterValue(&thickness, gauss);
     6516                surface_input->GetParameterDerivativeValue(&slope[0],&xyz_list[0][0],gauss);
     6517
     6518                driving_stress_baseline=matpar->GetRhoIce()*matpar->GetG();
     6519
     6520                for(i=0;i<NUMVERTICES;i++) for(j=0;j<NDOF2;j++) pe->values[i*NDOF2+j]+= -driving_stress_baseline*slope[j]*Jdet*gauss->weight*basis[i];
     6521        }
     6522
     6523        /*Clean up and return*/
     6524        delete gauss;
     6525        return pe;
     6526}
     6527/*}}}*/
     6528/*FUNCTION Penta::CreatePVectorDiagnosticStokes {{{1*/
     6529ElementVector* Penta::CreatePVectorDiagnosticStokes(void){
     6530
     6531        /*compute all load vectors for this element*/
     6532        ElementVector* pe1=CreatePVectorDiagnosticStokesViscous();
     6533        ElementVector* pe2=CreatePVectorDiagnosticStokesShelf();
     6534        ElementVector* pe =new ElementVector(pe1,pe2);
     6535
     6536        /*clean-up and return*/
     6537        delete pe1;
     6538        delete pe2;
     6539        return pe;
     6540}
     6541/*}}}*/
     6542/*FUNCTION Penta::CreatePVectorDiagnosticStokesViscous {{{1*/
     6543ElementVector* Penta::CreatePVectorDiagnosticStokesViscous(void){
     6544
     6545        /*Constants*/
     6546        const int numdofbubble=NDOF4*NUMVERTICES+NDOF3*1;
     6547
     6548        /*Intermediaries*/
     6549        int        i,j,ig;
     6550        int        approximation;
     6551        double     Jdet,viscosity;
     6552        double     gravity,rho_ice,stokesreconditioning;
     6553        double     xyz_list[NUMVERTICES][3];
     6554        double     epsilon[6]; /* epsilon=[exx,eyy,ezz,exy,exz,eyz];*/
     6555        double     l1l7[7]; //for the six nodes and the bubble
     6556        double     B[8][numdofbubble];
     6557        double     B_prime[8][numdofbubble];
     6558        double     B_prime_bubble[8][3];
     6559        double     D[8][8]={0.0};
     6560        double     D_scalar;
     6561        double     Pe_gaussian[numdofbubble]={0.0}; //for the six nodes and the bubble
     6562        double     Ke_temp[numdofbubble][3]={0.0}; //for the six nodes and the bubble
     6563        double     Ke_gaussian[numdofbubble][3];
     6564        GaussPenta *gauss=NULL;
     6565
     6566        /*Initialize Element vector and return if necessary*/
     6567        inputs->GetParameterValue(&approximation,ApproximationEnum);
     6568        if(approximation!=StokesApproximationEnum && approximation!=MacAyealStokesApproximationEnum && approximation!=PattynStokesApproximationEnum) return NULL;
     6569        ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters,StokesApproximationEnum);
     6570
     6571        /*Retrieve all inputs and parameters*/
     6572        this->parameters->FindParam(&stokesreconditioning,DiagnosticStokesreconditioningEnum);
     6573        rho_ice=matpar->GetRhoIce();
     6574        gravity=matpar->GetG();
     6575        GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
     6576        Input* vx_input=inputs->GetInput(VxEnum);   _assert_(vx_input);
     6577        Input* vy_input=inputs->GetInput(VyEnum);   _assert_(vy_input);
     6578        Input* vz_input=inputs->GetInput(VzEnum);   _assert_(vz_input);
     6579
     6580        /* Start  looping on the number of gaussian points: */
     6581        gauss=new GaussPenta(5,5);
     6582        for (ig=gauss->begin();ig<gauss->end();ig++){
     6583
     6584                gauss->GaussPoint(ig);
     6585
     6586                GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss);
     6587                GetBStokes(&B[0][0],&xyz_list[0][0],gauss);
     6588                GetBprimeStokes(&B_prime[0][0],&xyz_list[0][0], gauss);
     6589                GetNodalFunctionsMINI(&l1l7[0], gauss);
     6590
     6591                this->GetStrainRate3d(&epsilon[0],&xyz_list[0][0],gauss,vx_input,vy_input,vz_input);
     6592                matice->GetViscosity3dStokes(&viscosity,&epsilon[0]);
     6593
     6594                for(i=0;i<NUMVERTICES+1;i++){
     6595                        Pe_gaussian[i*NDOF4+2]+=-rho_ice*gravity*Jdet*gauss->weight*l1l7[i];
     6596                }
     6597
     6598                /*Get bubble part of Bprime */
     6599                for(i=0;i<8;i++) for(j=0;j<3;j++) B_prime_bubble[i][j]=B_prime[i][j+24];
     6600
     6601                D_scalar=gauss->weight*Jdet;
     6602                for (i=0;i<6;i++) D[i][i]=D_scalar*2*viscosity;
     6603                for (i=6;i<8;i++) D[i][i]=-D_scalar*stokesreconditioning;
     6604
     6605                TripleMultiply(&B[0][0],8,numdofbubble,1,
     6606                                        &D[0][0],8,8,0,
     6607                                        &B_prime_bubble[0][0],8,3,0,
     6608                                        &Ke_gaussian[0][0],0);
     6609
     6610                for(i=0;i<numdofbubble;i++) for(j=0;j<NDOF3;j++) Ke_temp[i][j]+=Ke_gaussian[i][j];
     6611        }
     6612
     6613        /*Condensation*/
     6614        ReduceVectorStokes(pe->values, &Ke_temp[0][0], &Pe_gaussian[0]);
     6615
     6616        /*Clean up and return*/
     6617        delete gauss;
     6618        return pe;
     6619}
     6620/*}}}*/
     6621/*FUNCTION Penta::CreatePVectorDiagnosticStokesShelf{{{1*/
     6622ElementVector* Penta::CreatePVectorDiagnosticStokesShelf(void){
     6623
     6624        /*Intermediaries*/
     6625        int         i,j,ig;
     6626        int         approximation,shelf_dampening;
     6627        double      gravity,rho_water,bed,water_pressure;
     6628        double      damper,normal_vel,vx,vy,vz,dt;
     6629        double          xyz_list_tria[NUMVERTICES2D][3];
     6630        double      xyz_list[NUMVERTICES][3];
     6631        double          bed_normal[3];
     6632        double      dz[3];
     6633        double      basis[6]; //for the six nodes of the penta
     6634        double      Jdet2d;
     6635        GaussPenta  *gauss=NULL;
     6636
     6637        /*Initialize Element vector and return if necessary*/
     6638        if(!IsOnBed() || !IsOnShelf()) return NULL;
     6639        inputs->GetParameterValue(&approximation,ApproximationEnum);
     6640        this->parameters->FindParam(&shelf_dampening,DiagnosticShelfDampeningEnum);
     6641        if(approximation!=StokesApproximationEnum && approximation!=MacAyealStokesApproximationEnum && approximation!=PattynStokesApproximationEnum) return NULL;
     6642        ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters,StokesApproximationEnum);
     6643
     6644        /*Retrieve all inputs and parameters*/
     6645        rho_water=matpar->GetRhoWater();
     6646        gravity=matpar->GetG();
     6647        GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
     6648        Input* bed_input=inputs->GetInput(BedEnum); _assert_(bed_input);
     6649        Input* vx_input=inputs->GetInput(VxEnum);   _assert_(vx_input);
     6650        Input* vy_input=inputs->GetInput(VyEnum);   _assert_(vy_input);
     6651        Input* vz_input=inputs->GetInput(VzEnum);   _assert_(vz_input);
     6652
     6653        for(i=0;i<NUMVERTICES2D;i++) for(j=0;j<3;j++) xyz_list_tria[i][j]=xyz_list[i][j];
     6654
     6655        /* Start looping on the number of gauss 2d (nodes on the bedrock) */
     6656        gauss=new GaussPenta(0,1,2,2);
     6657        for(ig=gauss->begin();ig<gauss->end();ig++){
     6658
     6659                gauss->GaussPoint(ig);
     6660
     6661                GetTriaJacobianDeterminant(&Jdet2d, &xyz_list_tria[0][0], gauss);
     6662                GetNodalFunctionsP1(basis, gauss);
     6663
     6664                BedNormal(&bed_normal[0],xyz_list_tria);
     6665                bed_input->GetParameterValue(&bed, gauss);
     6666                if(shelf_dampening){ //add dampening to avoid too high vertical velocities when not in hydrostatic equilibrium
     6667                        bed_input->GetParameterDerivativeValue(&dz[0],&xyz_list[0][0],gauss);
     6668                        vx_input->GetParameterValue(&vx, gauss);
     6669                        vy_input->GetParameterValue(&vy, gauss);
     6670                        vz_input->GetParameterValue(&vz, gauss);
     6671                        dt=0;
     6672                        normal_vel=bed_normal[0]*vx+bed_normal[1]*vy+bed_normal[2]*vz;
     6673                        damper=gravity*rho_water*pow(1+pow(dz[0],2)+pow(dz[1],2),0.5)*normal_vel*dt;
     6674                }
     6675                else damper=0;
     6676                water_pressure=gravity*rho_water*bed;
     6677
     6678                for(i=0;i<NUMVERTICES;i++) for(j=0;j<3;j++) pe->values[i*NDOF4+j]+=(water_pressure+damper)*gauss->weight*Jdet2d*basis[i]*bed_normal[j];
     6679        }
     6680
     6681        /*Clean up and return*/
     6682        delete gauss;
     6683        return pe;
     6684}
     6685/*}}}*/
     6686/*FUNCTION Penta::CreatePVectorDiagnosticVert {{{1*/
     6687ElementVector* Penta::CreatePVectorDiagnosticVert(void){
     6688
     6689        /*compute all load vectors for this element*/
     6690        ElementVector* pe1=CreatePVectorDiagnosticVertVolume();
     6691        ElementVector* pe2=CreatePVectorDiagnosticVertBase();
     6692        ElementVector* pe =new ElementVector(pe1,pe2);
     6693
     6694        /*clean-up and return*/
     6695        delete pe1;
     6696        delete pe2;
     6697        return pe;
     6698}
     6699/*}}}*/
     6700/*FUNCTION Penta::CreatePVectorDiagnosticVertVolume {{{1*/
     6701ElementVector* Penta::CreatePVectorDiagnosticVertVolume(void){
     6702
     6703        /*Constants*/
     6704        const int  numdof=NDOF1*NUMVERTICES;
     6705
     6706        /*Intermediaries*/
     6707        int        i,ig;
     6708        int        approximation;
     6709        double     Jdet;
     6710        double     xyz_list[NUMVERTICES][3];
     6711        double     dudx,dvdy,dwdz;
     6712        double     du[3],dv[3],dw[3];
     6713        double     basis[6];
     6714        GaussPenta *gauss=NULL;
     6715
     6716        /*Initialize Element vector*/
     6717        ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters);
     6718
     6719        /*Retrieve all inputs and parameters*/
     6720        GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
     6721        inputs->GetParameterValue(&approximation,ApproximationEnum);
     6722        Input* vx_input=inputs->GetInput(VxEnum); _assert_(vx_input);
     6723        Input* vy_input=inputs->GetInput(VyEnum); _assert_(vy_input);
     6724        Input* vzstokes_input=NULL;
     6725        if(approximation==PattynStokesApproximationEnum || approximation==MacAyealStokesApproximationEnum){
     6726                vzstokes_input=inputs->GetInput(VzStokesEnum); _assert_(vzstokes_input);
     6727        }
     6728
     6729        /* Start  looping on the number of gaussian points: */
     6730        gauss=new GaussPenta(2,2);
     6731        for (ig=gauss->begin();ig<gauss->end();ig++){
     6732
     6733                gauss->GaussPoint(ig);
     6734
     6735                GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss);
     6736                GetNodalFunctionsP1(basis, gauss);
     6737
     6738                vx_input->GetParameterDerivativeValue(&du[0],&xyz_list[0][0],gauss);
     6739                vy_input->GetParameterDerivativeValue(&dv[0],&xyz_list[0][0],gauss);
     6740                if(approximation==PattynStokesApproximationEnum || approximation==MacAyealStokesApproximationEnum){
     6741                        vzstokes_input->GetParameterDerivativeValue(&dw[0],&xyz_list[0][0],gauss);
     6742                        dwdz=dw[2];
     6743                }
     6744                else dwdz=0;
     6745                dudx=du[0];
     6746                dvdy=dv[1];
     6747
     6748                for (i=0;i<numdof;i++) pe->values[i] += (dudx+dvdy+dwdz)*Jdet*gauss->weight*basis[i];
     6749        }
     6750
     6751        /*Clean up and return*/
     6752        delete gauss;
     6753        return pe;
     6754}
     6755/*}}}*/
     6756/*FUNCTION Penta::CreatePVectorDiagnosticVertBase {{{1*/
     6757ElementVector* Penta::CreatePVectorDiagnosticVertBase(void){
     6758
     6759
     6760        /*Constants*/
     6761        const int    numdof=NDOF1*NUMVERTICES;
     6762
     6763        /*Intermediaries */
     6764        int        i,j,ig;
     6765        int        approximation;
     6766        double     xyz_list[NUMVERTICES][3];
     6767        double     xyz_list_tria[NUMVERTICES2D][3];
     6768        double     Jdet2d;
     6769        double     vx,vy,vz,dbdx,dbdy,basalmeltingvalue;
     6770        double     slope[3];
     6771        double     basis[NUMVERTICES];
     6772        GaussPenta* gauss=NULL;
     6773
     6774        if (!IsOnBed()) return NULL;
     6775
     6776        /*Initialize Element vector*/
     6777        ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters);
     6778
     6779        /*Retrieve all inputs and parameters*/
     6780        GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
     6781        for(i=0;i<NUMVERTICES2D;i++) for(j=0;j<3;j++) xyz_list_tria[i][j]=xyz_list[i][j];
     6782        inputs->GetParameterValue(&approximation,ApproximationEnum);
     6783        Input* bed_input=inputs->GetInput(BedEnum);                                _assert_(bed_input);
     6784        Input* basal_melting_input=inputs->GetInput(BasalforcingsMeltingRateEnum); _assert_(basal_melting_input);
     6785        Input* vx_input=inputs->GetInput(VxEnum);                                  _assert_(vx_input);
     6786        Input* vy_input=inputs->GetInput(VyEnum);                                  _assert_(vy_input);
     6787        Input* vzstokes_input=NULL;
     6788        if(approximation==PattynStokesApproximationEnum || approximation==MacAyealStokesApproximationEnum){
     6789                vzstokes_input=inputs->GetInput(VzStokesEnum);       _assert_(vzstokes_input);
     6790        }
     6791
     6792        /* Start  looping on the number of gaussian points: */
     6793        gauss=new GaussPenta(0,1,2,2);
     6794        for(ig=gauss->begin();ig<gauss->end();ig++){
     6795
     6796                gauss->GaussPoint(ig);
     6797
     6798                basal_melting_input->GetParameterValue(&basalmeltingvalue, gauss);
     6799                bed_input->GetParameterDerivativeValue(&slope[0],&xyz_list[0][0],gauss);
     6800                vx_input->GetParameterValue(&vx, gauss);
     6801                vy_input->GetParameterValue(&vy, gauss);
     6802                if(approximation==PattynStokesApproximationEnum || approximation==MacAyealStokesApproximationEnum){
     6803                        vzstokes_input->GetParameterValue(&vz, gauss);
     6804                }
     6805                else vz=0;
     6806
     6807                dbdx=slope[0];
     6808                dbdy=slope[1];
     6809
     6810                GetTriaJacobianDeterminant(&Jdet2d, &xyz_list_tria[0][0],gauss);
     6811                GetNodalFunctionsP1(&basis[0], gauss);
     6812
     6813                for(i=0;i<numdof;i++) pe->values[i]+=-Jdet2d*gauss->weight*(vx*dbdx+vy*dbdy-vz-basalmeltingvalue)*basis[i];
     6814        }
     6815
     6816        /*Clean up and return*/
     6817        delete gauss;
     6818        return pe;
     6819}
     6820/*}}}*/
     6821/*FUNCTION Penta::GetSolutionFromInputsDiagnosticHoriz{{{1*/
     6822void  Penta::GetSolutionFromInputsDiagnosticHoriz(Vec solution){
     6823
     6824        const int    numdof=NDOF2*NUMVERTICES;
     6825
     6826        int          i;
     6827        int          approximation;
     6828        int*         doflist=NULL;
     6829        double       vx,vy;
     6830        double       values[numdof];
     6831        GaussPenta*  gauss;
     6832
     6833        /*Get approximation enum and dof list: */
     6834        inputs->GetParameterValue(&approximation,ApproximationEnum);
     6835        Input* vx_input=inputs->GetInput(VxEnum); _assert_(vx_input);
     6836        Input* vy_input=inputs->GetInput(VyEnum); _assert_(vy_input);
     6837
     6838        /*If the element is a coupling, do nothing: every node is also on an other elements
     6839         * (as coupling is between MacAyeal and Pattyn) so the other element will take care of it*/
     6840        GetDofList(&doflist,approximation,GsetEnum);
     6841
     6842        /*Ok, we have vx and vy in values, fill in vx and vy arrays: */
     6843        /*P1 element only for now*/
     6844        gauss=new GaussPenta();
     6845        for(i=0;i<NUMVERTICES;i++){
     6846
     6847                /*Recover vx and vy*/
     6848                gauss->GaussVertex(i);
     6849                vx_input->GetParameterValue(&vx,gauss);
     6850                vy_input->GetParameterValue(&vy,gauss);
     6851                values[i*NDOF2+0]=vx;
     6852                values[i*NDOF2+1]=vy;
     6853        }
     6854
     6855        /*Add value to global vector*/
     6856        VecSetValues(solution,numdof,doflist,(const double*)values,INSERT_VALUES);
     6857
     6858        /*Free ressources:*/
     6859        delete gauss;
     6860        xfree((void**)&doflist);
     6861}
     6862/*}}}*/
     6863/*FUNCTION Penta::GetSolutionFromInputsDiagnosticHutter{{{1*/
     6864void  Penta::GetSolutionFromInputsDiagnosticHutter(Vec solution){
     6865
     6866        const int    numdof=NDOF2*NUMVERTICES;
     6867
     6868        int          i;
     6869        int*         doflist=NULL;
     6870        double       vx,vy;
     6871        double       values[numdof];
     6872        GaussPenta*  gauss=NULL;
     6873
     6874        /*Get dof list: */
     6875        GetDofList(&doflist,NoneApproximationEnum,GsetEnum);
     6876        Input* vx_input=inputs->GetInput(VxEnum); _assert_(vx_input);
     6877        Input* vy_input=inputs->GetInput(VyEnum); _assert_(vy_input);
     6878
     6879        /*Ok, we have vx and vy in values, fill in vx and vy arrays: */
     6880        /*P1 element only for now*/
     6881        gauss=new GaussPenta();
     6882        for(i=0;i<NUMVERTICES;i++){
     6883                /*Recover vx and vy*/
     6884                gauss->GaussVertex(i);
     6885                vx_input->GetParameterValue(&vx,gauss);
     6886                vy_input->GetParameterValue(&vy,gauss);
     6887                values[i*NDOF2+0]=vx;
     6888                values[i*NDOF2+1]=vy;
     6889        }
     6890
     6891        /*Add value to global vector*/
     6892        VecSetValues(solution,numdof,doflist,(const double*)values,INSERT_VALUES);
     6893
     6894        /*Free ressources:*/
     6895        delete gauss;
     6896        xfree((void**)&doflist);
     6897}
     6898/*}}}*/
     6899/*FUNCTION Penta::GetSolutionFromInputsDiagnosticVert{{{1*/
     6900void  Penta::GetSolutionFromInputsDiagnosticVert(Vec solution){
     6901
     6902        const int    numdof=NDOF1*NUMVERTICES;
     6903
     6904        int          i;
     6905        int*         doflist=NULL;
     6906        double       vz;
     6907        double       values[numdof];
     6908        GaussPenta*  gauss=NULL;
     6909
     6910        /*Get dof list: */
     6911        GetDofList(&doflist,NoneApproximationEnum,GsetEnum);
     6912        Input* vz_input=inputs->GetInput(VzEnum); _assert_(vz_input);
     6913
     6914        /*Ok, we have vx and vy in values, fill in vx and vy arrays: */
     6915        /*P1 element only for now*/
     6916        gauss=new GaussPenta();
     6917        for(i=0;i<NUMVERTICES;i++){
     6918                /*Recover vz */
     6919                gauss->GaussVertex(i);
     6920                vz_input->GetParameterValue(&vz,gauss);
     6921                values[i]=vz;
     6922        }
     6923
     6924        /*Add value to global vector*/
     6925        VecSetValues(solution,numdof,doflist,(const double*)values,INSERT_VALUES);
     6926
     6927        /*Free ressources:*/
     6928        delete gauss;
     6929        xfree((void**)&doflist);
     6930}
     6931/*}}}*/
     6932/*FUNCTION Penta::GetSolutionFromInputsDiagnosticStokes{{{1*/
     6933void  Penta::GetSolutionFromInputsDiagnosticStokes(Vec solution){
     6934
     6935        const int    numdof=NDOF4*NUMVERTICES;
     6936
     6937        int          i;
     6938        int*         doflist=NULL;
     6939        double       vx,vy,vz,p;
     6940        double       stokesreconditioning;
     6941        double       values[numdof];
     6942        GaussPenta   *gauss;
     6943
     6944        /*Get dof list: */
     6945        GetDofList(&doflist,StokesApproximationEnum,GsetEnum);
     6946        Input* vx_input=inputs->GetInput(VxEnum);       _assert_(vx_input);
     6947        Input* vy_input=inputs->GetInput(VyEnum);       _assert_(vy_input);
     6948        Input* vz_input=inputs->GetInput(VzEnum);       _assert_(vz_input);
     6949        Input* p_input =inputs->GetInput(PressureEnum); _assert_(p_input);
     6950
     6951        /*Recondition pressure: */
     6952        this->parameters->FindParam(&stokesreconditioning,DiagnosticStokesreconditioningEnum);
     6953
     6954        /*Ok, we have vx vy vz and P in values, fill in vx vy vz P arrays: */
     6955        /*P1 element only for now*/
     6956        gauss=new GaussPenta();
     6957        for(i=0;i<NUMVERTICES;i++){
     6958                gauss->GaussVertex(i);
     6959                vx_input->GetParameterValue(&vx,gauss);
     6960                vy_input->GetParameterValue(&vy,gauss);
     6961                vz_input->GetParameterValue(&vz,gauss);
     6962                p_input ->GetParameterValue(&p ,gauss);
     6963                values[i*NDOF4+0]=vx;
     6964                values[i*NDOF4+1]=vy;
     6965                values[i*NDOF4+2]=vz;
     6966                values[i*NDOF4+3]=p/stokesreconditioning;
     6967        }
     6968
     6969        /*Add value to global vector*/
     6970        VecSetValues(solution,numdof,doflist,(const double*)values,INSERT_VALUES);
     6971
     6972        /*Free ressources:*/
     6973        delete gauss;
     6974        xfree((void**)&doflist);
     6975}
     6976/*}}}*/
     6977/*FUNCTION Penta::InputUpdateFromSolutionDiagnosticHoriz {{{1*/
     6978void  Penta::InputUpdateFromSolutionDiagnosticHoriz(double* solution){
     6979
     6980        int  approximation;
     6981
     6982        /*Recover inputs*/
     6983        inputs->GetParameterValue(&approximation,ApproximationEnum);
     6984
     6985        /*MacAyeal, everything is done by the element on bed*/
     6986        if (approximation==MacAyealApproximationEnum){
     6987                if (!IsOnBed()){
     6988                        /*Do nothing. Element on bed will take care of it*/
     6989                        return;
     6990                }
     6991                else{
     6992                        InputUpdateFromSolutionDiagnosticMacAyeal(solution);
     6993                        return;
     6994                }
     6995        }
     6996        else if (approximation==PattynApproximationEnum){
     6997                InputUpdateFromSolutionDiagnosticPattyn(solution);
     6998        }
     6999        else if (approximation==PattynStokesApproximationEnum){
     7000                InputUpdateFromSolutionDiagnosticPattynStokes(solution);
     7001        }
     7002        else if (approximation==MacAyealStokesApproximationEnum){
     7003                InputUpdateFromSolutionDiagnosticMacAyealStokes(solution);
     7004        }
     7005        else if (approximation==StokesApproximationEnum || approximation==NoneApproximationEnum){
     7006                InputUpdateFromSolutionDiagnosticStokes(solution);
     7007        }
     7008        else if (approximation==MacAyealPattynApproximationEnum){
     7009                InputUpdateFromSolutionDiagnosticMacAyealPattyn(solution);
     7010        }
     7011}
     7012/*}}}*/
     7013/*FUNCTION Penta::InputUpdateFromSolutionDiagnosticMacAyeal {{{1*/
     7014void  Penta::InputUpdateFromSolutionDiagnosticMacAyeal(double* solution){
     7015
     7016        const int    numdof=NDOF2*NUMVERTICES;
     7017
     7018        int     i,dummy;
     7019        double  rho_ice,g;
     7020        double  values[numdof];
     7021        double  vx[NUMVERTICES];
     7022        double  vy[NUMVERTICES];
     7023        double  vz[NUMVERTICES];
     7024        double  vel[NUMVERTICES];
     7025        double  pressure[NUMVERTICES];
     7026        double  surface[NUMVERTICES];
     7027        double  xyz_list[NUMVERTICES][3];
     7028        int    *doflist = NULL;
     7029        double *vz_ptr  = NULL;
     7030        Penta  *penta   = NULL;
     7031
     7032        /*Get dof list: */
     7033        GetDofList(&doflist,MacAyealApproximationEnum,GsetEnum);
     7034
     7035        /*Use the dof list to index into the solution vector: */
     7036        for(i=0;i<numdof;i++) values[i]=solution[doflist[i]];
     7037
     7038        /*Ok, we have vx and vy in values, fill in vx and vy arrays and extrude */
     7039        for(i=0;i<3;i++){
     7040                vx[i]  =values[i*NDOF2+0];
     7041                vy[i]  =values[i*NDOF2+1];
     7042                vx[i+3]=vx[i];
     7043                vy[i+3]=vy[i];
     7044
     7045                /*Check solution*/
     7046                if(isnan(vx[i])) _error_("NaN found in solution vector");
     7047                if(isnan(vy[i])) _error_("NaN found in solution vector");
     7048        }
     7049
     7050        /*Get parameters fro pressure computation*/
     7051        rho_ice=matpar->GetRhoIce();
     7052        g=matpar->GetG();
     7053
     7054        /*Start looping over all elements above current element and update all inputs*/
     7055        penta=this;
     7056        for(;;){
     7057
     7058                /*Get node data: */
     7059                GetVerticesCoordinates(&xyz_list[0][0],penta->nodes,NUMVERTICES);
     7060
     7061                /*Now Compute vel*/
     7062                Input* vz_input=inputs->GetInput(VzEnum);
     7063                if (vz_input){
     7064                        if (vz_input->Enum()!=PentaVertexInputEnum) _error_("Cannot compute Vel as Vz is of type %s",EnumToStringx(vz_input->Enum()));
     7065                        vz_input->GetValuesPtr(&vz_ptr,&dummy);
     7066                        for(i=0;i<NUMVERTICES;i++) vz[i]=vz_ptr[i];
     7067                }
     7068                else{for(i=0;i<NUMVERTICES;i++) vz[i]=0.0;}
     7069                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);
     7070
     7071                /*Now compute pressure*/
     7072                GetParameterListOnVertices(&surface[0],SurfaceEnum);
     7073                for(i=0;i<NUMVERTICES;i++) pressure[i]=rho_ice*g*(surface[i]-xyz_list[i][2]);
     7074
     7075                /*Now, we have to move the previous Vx and Vy inputs  to old
     7076                 * status, otherwise, we'll wipe them off: */
     7077                penta->inputs->ChangeEnum(VxEnum,VxPicardEnum);
     7078                penta->inputs->ChangeEnum(VyEnum,VyPicardEnum);
     7079                penta->inputs->ChangeEnum(PressureEnum,PressurePicardEnum);
     7080
     7081                /*Add vx and vy as inputs to the tria element: */
     7082                penta->inputs->AddInput(new PentaVertexInput(VxEnum,vx));
     7083                penta->inputs->AddInput(new PentaVertexInput(VyEnum,vy));
     7084                penta->inputs->AddInput(new PentaVertexInput(VelEnum,vel));
     7085                penta->inputs->AddInput(new PentaVertexInput(PressureEnum,pressure));
     7086
     7087                /*Stop if we have reached the surface*/
     7088                if (penta->IsOnSurface()) break;
     7089
     7090                /* get upper Penta*/
     7091                penta=penta->GetUpperElement(); _assert_(penta->Id()!=this->id);
     7092        }
     7093       
     7094        /*Free ressources:*/
     7095        xfree((void**)&doflist);
     7096}
     7097/*}}}*/
     7098/*FUNCTION Penta::InputUpdateFromSolutionDiagnosticMacAyealPattyn {{{1*/
     7099void  Penta::InputUpdateFromSolutionDiagnosticMacAyealPattyn(double* solution){
     7100
     7101        const int    numdof=NDOF2*NUMVERTICES;
     7102        const int    numdof2d=NDOF2*NUMVERTICES2D;
     7103
     7104        int     i,dummy;
     7105        double  rho_ice,g;
     7106        double  macayeal_values[numdof];
     7107        double  pattyn_values[numdof];
     7108        double  vx[NUMVERTICES];
     7109        double  vy[NUMVERTICES];
     7110        double  vz[NUMVERTICES];
     7111        double  vel[NUMVERTICES];
     7112        double  pressure[NUMVERTICES];
     7113        double  surface[NUMVERTICES];
     7114        double  xyz_list[NUMVERTICES][3];
     7115        int*    doflistp = NULL;
     7116        int*    doflistm = NULL;
     7117        double  *vz_ptr  = NULL;
     7118        Penta   *penta   = NULL;
     7119
     7120        /*OK, we have to add results of this element for pattyn
     7121         * and results from the penta at base for macayeal. Now recover results*/
     7122        penta=GetBasalElement();
     7123
     7124        /*Get dof listof this element (pattyn dofs) and of the penta at base (macayeal dofs): */
     7125        GetDofList(&doflistp,PattynApproximationEnum,GsetEnum);
     7126        penta->GetDofList(&doflistm,MacAyealApproximationEnum,GsetEnum);
     7127
     7128        /*Get node data: */
     7129        GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
     7130
     7131        /*Use the dof list to index into the solution vector: */
     7132        for(i=0;i<numdof2d;i++){
     7133                pattyn_values[i]=solution[doflistp[i]];
     7134                macayeal_values[i]=solution[doflistm[i]];
     7135        }
     7136        for(i=numdof2d;i<numdof;i++){
     7137                pattyn_values[i]=solution[doflistp[i]];
     7138                macayeal_values[i]=macayeal_values[i-numdof2d];
     7139        }
     7140
     7141        /*Ok, we have vx and vy in values, fill in vx and vy arrays: */
     7142        for(i=0;i<NUMVERTICES;i++){
     7143                vx[i]=macayeal_values[i*NDOF2+0]+pattyn_values[i*NDOF2+0];
     7144                vy[i]=macayeal_values[i*NDOF2+1]+pattyn_values[i*NDOF2+1];
     7145
     7146                /*Check solution*/
     7147                if(isnan(vx[i])) _error_("NaN found in solution vector");
     7148                if(isnan(vy[i])) _error_("NaN found in solution vector");
     7149        }
     7150
     7151        /*Get Vz*/
     7152        Input* vz_input=inputs->GetInput(VzEnum);
     7153        if (vz_input){
     7154                if (vz_input->Enum()!=PentaVertexInputEnum){
     7155                        _error_("Cannot compute Vel as Vz is of type %s",EnumToStringx(vz_input->Enum()));
     7156                }
     7157                vz_input->GetValuesPtr(&vz_ptr,&dummy);
     7158                for(i=0;i<NUMVERTICES;i++) vz[i]=vz_ptr[i];
     7159        }
     7160        else{
     7161                for(i=0;i<NUMVERTICES;i++) vz[i]=0.0;
     7162        }
     7163
     7164        /*Now Compute vel*/
     7165        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);
     7166
     7167        /*For pressure: we have not computed pressure in this analysis, for this element. We are in 3D,
     7168         *so the pressure is just the pressure at the z elevation: */
     7169        rho_ice=matpar->GetRhoIce();
     7170        g=matpar->GetG();
     7171        GetParameterListOnVertices(&surface[0],SurfaceEnum);
     7172        for(i=0;i<NUMVERTICES;i++) pressure[i]=rho_ice*g*(surface[i]-xyz_list[i][2]);
     7173
     7174        /*Now, we have to move the previous Vx and Vy inputs  to old
     7175         * status, otherwise, we'll wipe them off: */
     7176        this->inputs->ChangeEnum(VxEnum,VxPicardEnum);
     7177        this->inputs->ChangeEnum(VyEnum,VyPicardEnum);
     7178        this->inputs->ChangeEnum(PressureEnum,PressurePicardEnum);
     7179
     7180        /*Add vx and vy as inputs to the tria element: */
     7181        this->inputs->AddInput(new PentaVertexInput(VxEnum,vx));
     7182        this->inputs->AddInput(new PentaVertexInput(VyEnum,vy));
     7183        this->inputs->AddInput(new PentaVertexInput(VelEnum,vel));
     7184        this->inputs->AddInput(new PentaVertexInput(PressureEnum,pressure));
     7185
     7186        /*Free ressources:*/
     7187        xfree((void**)&doflistp);
     7188        xfree((void**)&doflistm);
     7189}
     7190/*}}}*/
     7191/*FUNCTION Penta::InputUpdateFromSolutionDiagnosticMacAyealStokes {{{1*/
     7192void  Penta::InputUpdateFromSolutionDiagnosticMacAyealStokes(double* solution){
     7193
     7194        const int    numdofm=NDOF2*NUMVERTICES;
     7195        const int    numdofs=NDOF4*NUMVERTICES;
     7196        const int    numdof2d=NDOF2*NUMVERTICES2D;
     7197
     7198        int     i,dummy;
     7199        double  stokesreconditioning;
     7200        double  macayeal_values[numdofm];
     7201        double  stokes_values[numdofs];
     7202        double  vx[NUMVERTICES];
     7203        double  vy[NUMVERTICES];
     7204        double  vz[NUMVERTICES];
     7205        double  vzmacayeal[NUMVERTICES];
     7206        double  vzstokes[NUMVERTICES];
     7207        double  vel[NUMVERTICES];
     7208        double  pressure[NUMVERTICES];
     7209        double  xyz_list[NUMVERTICES][3];
     7210        int*    doflistm        = NULL;
     7211        int*    doflists        = NULL;
     7212        double  *vzmacayeal_ptr = NULL;
     7213        Penta   *penta          = NULL;
     7214
     7215        /*OK, we have to add results of this element for macayeal
     7216         * and results from the penta at base for macayeal. Now recover results*/
     7217        penta=GetBasalElement();
     7218
     7219        /*Get dof listof this element (macayeal dofs) and of the penta at base (macayeal dofs): */
     7220        penta->GetDofList(&doflistm,MacAyealApproximationEnum,GsetEnum);
     7221        GetDofList(&doflists,StokesApproximationEnum,GsetEnum);
     7222        this->parameters->FindParam(&stokesreconditioning,DiagnosticStokesreconditioningEnum);
     7223
     7224        /*Get node data: */
     7225        GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
     7226
     7227        /*Use the dof list to index into the solution vector: */
     7228        for(i=0;i<numdof2d;i++){
     7229                macayeal_values[i]=solution[doflistm[i]];
     7230                macayeal_values[i+numdof2d]=solution[doflistm[i]];
     7231        }
     7232        for(i=0;i<numdofs;i++){
     7233                stokes_values[i]=solution[doflists[i]];
     7234        }
     7235
     7236        /*Ok, we have vx and vy in values, fill in vx and vy arrays: */
     7237        for(i=0;i<NUMVERTICES;i++){
     7238                vx[i]=stokes_values[i*NDOF4+0]+macayeal_values[i*NDOF2+0];
     7239                vy[i]=stokes_values[i*NDOF4+1]+macayeal_values[i*NDOF2+1];
     7240                vzstokes[i]=stokes_values[i*NDOF4+2];
     7241                pressure[i]=stokes_values[i*NDOF4+3]*stokesreconditioning;
     7242
     7243                /*Check solution*/
     7244                if(isnan(vx[i]))       _error_("NaN found in solution vector");
     7245                if(isnan(vy[i]))       _error_("NaN found in solution vector");
     7246                if(isnan(vzstokes[i])) _error_("NaN found in solution vector");
     7247                if(isnan(pressure[i])) _error_("NaN found in solution vector");
     7248        }
     7249
     7250        /*Get Vz*/
     7251        Input* vzmacayeal_input=inputs->GetInput(VzMacAyealEnum);
     7252        if (vzmacayeal_input){
     7253                if (vzmacayeal_input->Enum()!=PentaVertexInputEnum){
     7254                        _error_("Cannot compute Vel as VzMacAyeal is of type %s",EnumToStringx(vzmacayeal_input->Enum()));
     7255                }
     7256                vzmacayeal_input->GetValuesPtr(&vzmacayeal_ptr,&dummy);
     7257                for(i=0;i<NUMVERTICES;i++) vzmacayeal[i]=vzmacayeal_ptr[i];
     7258        }
     7259        else{
     7260                _error_("Cannot update solution as VzMacAyeal is not present");
     7261        }
     7262
     7263        /*Now Compute vel*/
     7264        for(i=0;i<NUMVERTICES;i++) {
     7265                vz[i]=vzmacayeal[i]+vzstokes[i];
     7266                vel[i]=pow( pow(vx[i],2.0) + pow(vy[i],2.0) + pow(vz[i],2.0) , 0.5);
     7267        }
     7268
     7269        /*Now, we have to move the previous Vx and Vy inputs  to old
     7270         * status, otherwise, we'll wipe them off: */
     7271        this->inputs->ChangeEnum(VxEnum,VxPicardEnum);
     7272        this->inputs->ChangeEnum(VyEnum,VyPicardEnum);
     7273        this->inputs->ChangeEnum(VzEnum,VzPicardEnum);
     7274        this->inputs->ChangeEnum(PressureEnum,PressurePicardEnum);
     7275
     7276        /*Add vx and vy as inputs to the tria element: */
     7277        this->inputs->AddInput(new PentaVertexInput(VxEnum,vx));
     7278        this->inputs->AddInput(new PentaVertexInput(VyEnum,vy));
     7279        this->inputs->AddInput(new PentaVertexInput(VzEnum,vz));
     7280        this->inputs->AddInput(new PentaVertexInput(VzStokesEnum,vzstokes));
     7281        this->inputs->AddInput(new PentaVertexInput(VelEnum,vel));
     7282        this->inputs->AddInput(new PentaVertexInput(PressureEnum,pressure));
     7283
     7284        /*Free ressources:*/
     7285        xfree((void**)&doflistm);
     7286        xfree((void**)&doflists);
     7287}
     7288/*}}}*/
     7289/*FUNCTION Penta::InputUpdateFromSolutionDiagnosticPattyn {{{1*/
     7290void  Penta::InputUpdateFromSolutionDiagnosticPattyn(double* solution){
     7291       
     7292        const int    numdof=NDOF2*NUMVERTICES;
     7293
     7294        int    i,dummy;
     7295        double rho_ice,g;
     7296        double values[numdof];
     7297        double vx[NUMVERTICES];
     7298        double vy[NUMVERTICES];
     7299        double vz[NUMVERTICES];
     7300        double vel[NUMVERTICES];
     7301        double pressure[NUMVERTICES];
     7302        double surface[NUMVERTICES];
     7303        double xyz_list[NUMVERTICES][3];
     7304        int*   doflist = NULL;
     7305
     7306        /*Get dof list: */
     7307        GetDofList(&doflist,PattynApproximationEnum,GsetEnum);
     7308
     7309        /*Get node data: */
     7310        GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
     7311
     7312        /*Use the dof list to index into the solution vector: */
     7313        for(i=0;i<numdof;i++) values[i]=solution[doflist[i]];
     7314
     7315        /*Ok, we have vx and vy in values, fill in vx and vy arrays: */
     7316        for(i=0;i<NUMVERTICES;i++){
     7317                vx[i]=values[i*NDOF2+0];
     7318                vy[i]=values[i*NDOF2+1];
     7319
     7320                /*Check solution*/
     7321                if(isnan(vx[i])) _error_("NaN found in solution vector");
     7322                if(isnan(vy[i])) _error_("NaN found in solution vector");
     7323        }
     7324
     7325        /*Get Vz*/
     7326        Input* vz_input=inputs->GetInput(VzEnum);
     7327        if (vz_input){
     7328                GetParameterListOnVertices(&vz[0],VzEnum);
     7329        }
     7330        else{
     7331                for(i=0;i<NUMVERTICES;i++) vz[i]=0.0;
     7332        }
     7333
     7334        /*Now Compute vel*/
     7335        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);
     7336
     7337        /*For pressure: we have not computed pressure in this analysis, for this element. We are in 3D,
     7338         *so the pressure is just the pressure at the z elevation: */
     7339        rho_ice=matpar->GetRhoIce();
     7340        g=matpar->GetG();
     7341        GetParameterListOnVertices(&surface[0],SurfaceEnum);
     7342        for(i=0;i<NUMVERTICES;i++) pressure[i]=rho_ice*g*(surface[i]-xyz_list[i][2]);
     7343
     7344        /*Now, we have to move the previous Vx and Vy inputs  to old
     7345         * status, otherwise, we'll wipe them off: */
     7346        this->inputs->ChangeEnum(VxEnum,VxPicardEnum);
     7347        this->inputs->ChangeEnum(VyEnum,VyPicardEnum);
     7348        this->inputs->ChangeEnum(PressureEnum,PressurePicardEnum);
     7349
     7350        /*Add vx and vy as inputs to the tria element: */
     7351        this->inputs->AddInput(new PentaVertexInput(VxEnum,vx));
     7352        this->inputs->AddInput(new PentaVertexInput(VyEnum,vy));
     7353        this->inputs->AddInput(new PentaVertexInput(VelEnum,vel));
     7354        this->inputs->AddInput(new PentaVertexInput(PressureEnum,pressure));
     7355
     7356        /*Free ressources:*/
     7357        xfree((void**)&doflist);
     7358}
     7359/*}}}*/
     7360/*FUNCTION Penta::InputUpdateFromSolutionDiagnosticPattynStokes {{{1*/
     7361void  Penta::InputUpdateFromSolutionDiagnosticPattynStokes(double* solution){
     7362
     7363        const int    numdofp=NDOF2*NUMVERTICES;
     7364        const int    numdofs=NDOF4*NUMVERTICES;
     7365
     7366        int    i,dummy;
     7367        double pattyn_values[numdofp];
     7368        double stokes_values[numdofs];
     7369        double vx[NUMVERTICES];
     7370        double vy[NUMVERTICES];
     7371        double vz[NUMVERTICES];
     7372        double vzpattyn[NUMVERTICES];
     7373        double vzstokes[NUMVERTICES];
     7374        double vel[NUMVERTICES];
     7375        double pressure[NUMVERTICES];
     7376        double xyz_list[NUMVERTICES][3];
     7377        double stokesreconditioning;
     7378        int*   doflistp      = NULL;
     7379        int*   doflists      = NULL;
     7380        double *vzpattyn_ptr = NULL;
     7381        Penta  *penta        = NULL;
     7382
     7383        /*OK, we have to add results of this element for pattyn
     7384         * and results from the penta at base for macayeal. Now recover results*/
     7385        penta=GetBasalElement();
     7386
     7387        /*Get dof listof this element (pattyn dofs) and of the penta at base (macayeal dofs): */
     7388        GetDofList(&doflistp,PattynApproximationEnum,GsetEnum);
     7389        GetDofList(&doflists,StokesApproximationEnum,GsetEnum);
     7390        this->parameters->FindParam(&stokesreconditioning,DiagnosticStokesreconditioningEnum);
     7391
     7392        /*Get node data: */
     7393        GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
     7394
     7395        /*Use the dof list to index into the solution vector: */
     7396        for(i=0;i<numdofp;i++) pattyn_values[i]=solution[doflistp[i]];
     7397        for(i=0;i<numdofs;i++) stokes_values[i]=solution[doflists[i]];
     7398
     7399        /*Ok, we have vx and vy in values, fill in vx and vy arrays: */
     7400        for(i=0;i<NUMVERTICES;i++){
     7401                vx[i]=stokes_values[i*NDOF4+0]+pattyn_values[i*NDOF2+0];
     7402                vy[i]=stokes_values[i*NDOF4+1]+pattyn_values[i*NDOF2+1];
     7403                vzstokes[i]=stokes_values[i*NDOF4+2];
     7404                pressure[i]=stokes_values[i*NDOF4+3]*stokesreconditioning;
     7405
     7406                /*Check solution*/
     7407                if(isnan(vx[i]))       _error_("NaN found in solution vector");
     7408                if(isnan(vy[i]))       _error_("NaN found in solution vector");
     7409                if(isnan(vzstokes[i])) _error_("NaN found in solution vector");
     7410                if(isnan(pressure[i])) _error_("NaN found in solution vector");
     7411        }
     7412
     7413        /*Get Vz*/
     7414        Input* vzpattyn_input=inputs->GetInput(VzPattynEnum);
     7415        if (vzpattyn_input){
     7416                if (vzpattyn_input->Enum()!=PentaVertexInputEnum){
     7417                        _error_("Cannot compute Vel as VzPattyn is of type %s",EnumToStringx(vzpattyn_input->Enum()));
     7418                }
     7419                vzpattyn_input->GetValuesPtr(&vzpattyn_ptr,&dummy);
     7420                for(i=0;i<NUMVERTICES;i++) vzpattyn[i]=vzpattyn_ptr[i];
     7421        }
     7422        else{
     7423                _error_("Cannot update solution as VzPattyn is not present");
     7424        }
     7425
     7426        /*Now Compute vel*/
     7427        for(i=0;i<NUMVERTICES;i++) {
     7428                vz[i]=vzpattyn[i]+vzstokes[i];
     7429                vel[i]=pow( pow(vx[i],2.0) + pow(vy[i],2.0) + pow(vz[i],2.0) , 0.5);
     7430        }
     7431
     7432        /*Now, we have to move the previous Vx and Vy inputs  to old
     7433         * status, otherwise, we'll wipe them off: */
     7434        this->inputs->ChangeEnum(VxEnum,VxPicardEnum);
     7435        this->inputs->ChangeEnum(VyEnum,VyPicardEnum);
     7436        this->inputs->ChangeEnum(VzEnum,VzPicardEnum);
     7437        this->inputs->ChangeEnum(PressureEnum,PressurePicardEnum);
     7438
     7439        /*Add vx and vy as inputs to the tria element: */
     7440        this->inputs->AddInput(new PentaVertexInput(VxEnum,vx));
     7441        this->inputs->AddInput(new PentaVertexInput(VyEnum,vy));
     7442        this->inputs->AddInput(new PentaVertexInput(VzEnum,vz));
     7443        this->inputs->AddInput(new PentaVertexInput(VzStokesEnum,vzstokes));
     7444        this->inputs->AddInput(new PentaVertexInput(VelEnum,vel));
     7445        this->inputs->AddInput(new PentaVertexInput(PressureEnum,pressure));
     7446
     7447        /*Free ressources:*/
     7448        xfree((void**)&doflistp);
     7449        xfree((void**)&doflists);
     7450}
     7451/*}}}*/
     7452/*FUNCTION Penta::InputUpdateFromSolutionDiagnosticHutter {{{1*/
     7453void  Penta::InputUpdateFromSolutionDiagnosticHutter(double* solution){
     7454       
     7455        const int    numdof=NDOF2*NUMVERTICES;
     7456
     7457        int     i,dummy;
     7458        double  rho_ice,g;
     7459        double  values[numdof];
     7460        double  vx[NUMVERTICES];
     7461        double  vy[NUMVERTICES];
     7462        double  vz[NUMVERTICES];
     7463        double  vel[NUMVERTICES];
     7464        double  pressure[NUMVERTICES];
     7465        double  surface[NUMVERTICES];
     7466        double  xyz_list[NUMVERTICES][3];
     7467        int*    doflist = NULL;
     7468        double* vz_ptr  = NULL;
     7469
     7470        /*Get dof list: */
     7471        GetDofList(&doflist,NoneApproximationEnum,GsetEnum);
     7472
     7473        /*Get node data: */
     7474        GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
     7475
     7476        /*Use the dof list to index into the solution vector: */
     7477        for(i=0;i<numdof;i++) values[i]=solution[doflist[i]];
     7478
     7479        /*Ok, we have vx and vy in values, fill in vx and vy arrays: */
     7480        for(i=0;i<NUMVERTICES;i++){
     7481                vx[i]=values[i*NDOF2+0];
     7482                vy[i]=values[i*NDOF2+1];
     7483
     7484                /*Check solution*/
     7485                if(isnan(vx[i])) _error_("NaN found in solution vector");
     7486                if(isnan(vy[i])) _error_("NaN found in solution vector");
     7487        }
     7488
     7489        /*Get Vz*/
     7490        Input* vz_input=inputs->GetInput(VzEnum);
     7491        if (vz_input){
     7492                if (vz_input->Enum()!=PentaVertexInputEnum){
     7493                        _error_("Cannot compute Vel as Vz is of type %s",EnumToStringx(vz_input->Enum()));
     7494                }
     7495                vz_input->GetValuesPtr(&vz_ptr,&dummy);
     7496                for(i=0;i<NUMVERTICES;i++) vz[i]=vz_ptr[i];
     7497        }
     7498        else{
     7499                for(i=0;i<NUMVERTICES;i++) vz[i]=0.0;
     7500        }
     7501
     7502        /*Now Compute vel*/
     7503        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);
     7504
     7505        /*For pressure: we have not computed pressure in this analysis, for this element. We are in 3D,
     7506         *so the pressure is just the pressure at the z elevation: */
     7507        rho_ice=matpar->GetRhoIce();
     7508        g=matpar->GetG();
     7509        GetParameterListOnVertices(&surface[0],SurfaceEnum);
     7510        for(i=0;i<NUMVERTICES;i++) pressure[i]=rho_ice*g*(surface[i]-xyz_list[i][2]);
     7511
     7512        /*Now, we have to move the previous Vx and Vy inputs  to old
     7513         * status, otherwise, we'll wipe them off: */
     7514        this->inputs->ChangeEnum(VxEnum,VxPicardEnum);
     7515        this->inputs->ChangeEnum(VyEnum,VyPicardEnum);
     7516        this->inputs->ChangeEnum(PressureEnum,PressurePicardEnum);
     7517
     7518        /*Add vx and vy as inputs to the tria element: */
     7519        this->inputs->AddInput(new PentaVertexInput(VxEnum,vx));
     7520        this->inputs->AddInput(new PentaVertexInput(VyEnum,vy));
     7521        this->inputs->AddInput(new TriaVertexInput(VelEnum,vel));
     7522        this->inputs->AddInput(new PentaVertexInput(PressureEnum,pressure));
     7523
     7524        /*Free ressources:*/
     7525        xfree((void**)&doflist);
     7526}
     7527/*}}}*/
     7528/*FUNCTION Penta::InputUpdateFromSolutionDiagnosticVert {{{1*/
     7529void  Penta::InputUpdateFromSolutionDiagnosticVert(double* solution){
     7530
     7531        const int numdof=NDOF1*NUMVERTICES;
     7532       
     7533        int      i,dummy;
     7534        int      approximation;
     7535        double   rho_ice,g;
     7536        double   values[numdof];
     7537        double   vx[NUMVERTICES];
     7538        double   vy[NUMVERTICES];
     7539        double   vz[NUMVERTICES];
     7540        double   vzmacayeal[NUMVERTICES];
     7541        double   vzpattyn[NUMVERTICES];
     7542        double   vzstokes[NUMVERTICES];
     7543        double   vel[NUMVERTICES];
     7544        double   pressure[NUMVERTICES];
     7545        double   surface[NUMVERTICES];
     7546        double   xyz_list[NUMVERTICES][3];
     7547        int*     doflist      = NULL;
     7548        double*  vx_ptr       = NULL;
     7549        double*  vy_ptr       = NULL;
     7550        double*  vzstokes_ptr = NULL;
     7551
     7552
     7553        /*Get the approximation and do nothing if the element in Stokes or None*/
     7554        inputs->GetParameterValue(&approximation,ApproximationEnum);
     7555        if(approximation==StokesApproximationEnum || approximation==NoneApproximationEnum){
     7556                return;
     7557        }
     7558
     7559        /*Get dof list and vertices coordinates: */
     7560        GetDofList(&doflist,NoneApproximationEnum,GsetEnum);
     7561        GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
     7562
     7563        /*Use the dof list to index into the solution vector vz: */
     7564        for(i=0;i<numdof;i++) values[i]=solution[doflist[i]];
     7565        for(i=0;i<NUMVERTICES;i++){
     7566                vz[i]=values[i*NDOF1+0];
     7567
     7568                /*Check solution*/
     7569                if(isnan(vz[i])) _error_("NaN found in solution vector");
     7570        }
     7571
     7572        /*Get Vx and Vy*/
     7573        Input* vx_input=inputs->GetInput(VxEnum);
     7574        if (vx_input){
     7575                if (vx_input->Enum()!=PentaVertexInputEnum) _error_("Cannot compute Vel as Vx is of type %s",EnumToStringx(vx_input->Enum()));
     7576                vx_input->GetValuesPtr(&vx_ptr,&dummy);
     7577                for(i=0;i<NUMVERTICES;i++) vx[i]=vx_ptr[i];
     7578        }
     7579        else for(i=0;i<NUMVERTICES;i++) vx[i]=0.0;
     7580
     7581        Input* vy_input=inputs->GetInput(VyEnum);
     7582        if (vy_input){
     7583                if (vy_input->Enum()!=PentaVertexInputEnum) _error_("Cannot compute Vel as Vy is of type %s",EnumToStringx(vy_input->Enum()));
     7584                vy_input->GetValuesPtr(&vy_ptr,&dummy);
     7585                for(i=0;i<NUMVERTICES;i++) vy[i]=vy_ptr[i];
     7586        }
     7587        else for(i=0;i<NUMVERTICES;i++) vy[i]=0.0;
     7588
     7589        /*Do some modifications if we actually have a PattynStokes or MacAyealStokes element*/
     7590        if(approximation==PattynStokesApproximationEnum){
     7591                Input* vzstokes_input=inputs->GetInput(VzStokesEnum);
     7592                if (vzstokes_input){
     7593                        if (vzstokes_input->Enum()!=PentaVertexInputEnum) _error_("Cannot compute Vel as VzStokes is of type %s",EnumToStringx(vy_input->Enum()));
     7594                        vzstokes_input->GetValuesPtr(&vzstokes_ptr,&dummy);
     7595                        for(i=0;i<NUMVERTICES;i++) vzstokes[i]=vzstokes_ptr[i];
     7596                }
     7597                else _error_("Cannot compute Vz as VzStokes in not present in PattynStokes element");
     7598                for(i=0;i<NUMVERTICES;i++){
     7599                        vzpattyn[i]=vz[i];
     7600                        vz[i]=vzpattyn[i]+vzstokes[i];
     7601                }
     7602        }
     7603        else if(approximation==MacAyealStokesApproximationEnum){
     7604                Input* vzstokes_input=inputs->GetInput(VzStokesEnum);
     7605                if (vzstokes_input){
     7606                        if (vzstokes_input->Enum()!=PentaVertexInputEnum) _error_("Cannot compute Vel as VzStokes is of type %s",EnumToStringx(vy_input->Enum()));
     7607                        vzstokes_input->GetValuesPtr(&vzstokes_ptr,&dummy);
     7608                        for(i=0;i<NUMVERTICES;i++) vzstokes[i]=vzstokes_ptr[i];
     7609                }
     7610                else _error_("Cannot compute Vz as VzStokes in not present in MacAyealStokes element");
     7611                for(i=0;i<NUMVERTICES;i++){
     7612                        vzmacayeal[i]=vz[i];
     7613                        vz[i]=vzmacayeal[i]+vzstokes[i];
     7614                }
     7615        }
     7616
     7617        /*Now Compute vel*/
     7618        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);
     7619
     7620        /*For pressure: we have not computed pressure in this analysis, for this element. We are in 3D,
     7621         *so the pressure is just the pressure at the z elevation: except it this is a PattynStokes element */
     7622        if(approximation!=PattynStokesApproximationEnum &&  approximation!=MacAyealStokesApproximationEnum){
     7623                rho_ice=matpar->GetRhoIce();
     7624                g=matpar->GetG();
     7625                GetParameterListOnVertices(&surface[0],SurfaceEnum);
     7626                for(i=0;i<NUMVERTICES;i++) pressure[i]=rho_ice*g*(surface[i]-xyz_list[i][2]);
     7627        }
     7628
     7629        /*Now, we have to move the previous Vz inputs to old
     7630         * status, otherwise, we'll wipe them off and add the new inputs: */
     7631        this->inputs->ChangeEnum(VzEnum,VzPicardEnum);
     7632
     7633        if(approximation!=PattynStokesApproximationEnum && approximation!=MacAyealStokesApproximationEnum){
     7634                this->inputs->ChangeEnum(PressureEnum,PressurePicardEnum);
     7635                this->inputs->AddInput(new PentaVertexInput(PressureEnum,pressure));
     7636        }
     7637        else if(approximation==PattynStokesApproximationEnum){
     7638                this->inputs->AddInput(new PentaVertexInput(VzPattynEnum,vzpattyn));
     7639        }
     7640        else if(approximation==MacAyealStokesApproximationEnum){
     7641                this->inputs->AddInput(new PentaVertexInput(VzMacAyealEnum,vzmacayeal));
     7642        }
     7643
     7644        this->inputs->AddInput(new PentaVertexInput(VzEnum,vz));
     7645        this->inputs->AddInput(new PentaVertexInput(VelEnum,vel));
     7646
     7647        /*Free ressources:*/
     7648        xfree((void**)&doflist);
     7649}
     7650/*}}}*/
     7651/*FUNCTION Penta::InputUpdateFromSolutionDiagnosticStokes {{{1*/
     7652void  Penta::InputUpdateFromSolutionDiagnosticStokes(double* solution){
     7653       
     7654        const int numdof=NDOF4*NUMVERTICES;
     7655
     7656        int     i;
     7657        double  values[numdof];
     7658        double  vx[NUMVERTICES];
     7659        double  vy[NUMVERTICES];
     7660        double  vz[NUMVERTICES];
     7661        double  vel[NUMVERTICES];
     7662        double  pressure[NUMVERTICES];
     7663        double  stokesreconditioning;
     7664        int*    doflist=NULL;
     7665
     7666        /*Get dof list: */
     7667        GetDofList(&doflist,StokesApproximationEnum,GsetEnum);
     7668
     7669        /*Use the dof list to index into the solution vector: */
     7670        for(i=0;i<numdof;i++) values[i]=solution[doflist[i]];
     7671
     7672        /*Ok, we have vx and vy in values, fill in all arrays: */
     7673        for(i=0;i<NUMVERTICES;i++){
     7674                vx[i]=values[i*NDOF4+0];
     7675                vy[i]=values[i*NDOF4+1];
     7676                vz[i]=values[i*NDOF4+2];
     7677                pressure[i]=values[i*NDOF4+3];
     7678
     7679                /*Check solution*/
     7680                if(isnan(vx[i]))       _error_("NaN found in solution vector");
     7681                if(isnan(vy[i]))       _error_("NaN found in solution vector");
     7682                if(isnan(vz[i]))       _error_("NaN found in solution vector");
     7683                if(isnan(pressure[i])) _error_("NaN found in solution vector");
     7684        }
     7685
     7686        /*Recondition pressure and compute vel: */
     7687        this->parameters->FindParam(&stokesreconditioning,DiagnosticStokesreconditioningEnum);
     7688        for(i=0;i<NUMVERTICES;i++) pressure[i]=pressure[i]*stokesreconditioning;
     7689        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);
     7690       
     7691        /*Now, we have to move the previous inputs  to old
     7692         * status, otherwise, we'll wipe them off: */
     7693        this->inputs->ChangeEnum(VxEnum,VxPicardEnum);
     7694        this->inputs->ChangeEnum(VyEnum,VyPicardEnum);
     7695        this->inputs->ChangeEnum(VzEnum,VzPicardEnum);
     7696        this->inputs->ChangeEnum(PressureEnum,PressurePicardEnum);
     7697
     7698        /*Add vx and vy as inputs to the tria element: */
     7699        this->inputs->AddInput(new PentaVertexInput(VxEnum,vx));
     7700        this->inputs->AddInput(new PentaVertexInput(VyEnum,vy));
     7701        this->inputs->AddInput(new PentaVertexInput(VzEnum,vz));
     7702        this->inputs->AddInput(new PentaVertexInput(VelEnum,vel));
     7703        this->inputs->AddInput(new PentaVertexInput(PressureEnum,pressure));
     7704
     7705        /*Free ressources:*/
     7706        xfree((void**)&doflist);
     7707}
     7708/*}}}*/
     7709#endif
     7710
     7711#ifdef _HAVE_BALANCED_
     7712/*FUNCTION Penta::CreateKMatrixBalancethickness {{{1*/
     7713ElementMatrix* Penta::CreateKMatrixBalancethickness(void){
     7714
     7715        /*Figure out if this penta is collapsed. If so, then bailout, except if it is at the
     7716          bedrock, in which case we spawn a tria element using the 3 first nodes, and use it to build
     7717          the stiffness matrix. */
     7718        if (!IsOnBed()) return NULL;
     7719
     7720        /*Depth Averaging Vx and Vy*/
     7721        this->InputDepthAverageAtBase(VxEnum,VxAverageEnum);
     7722        this->InputDepthAverageAtBase(VyEnum,VyAverageEnum);
     7723
     7724        /*Spawn Tria element from the base of the Penta: */
     7725        Tria* tria=(Tria*)SpawnTria(0,1,2); //nodes 0, 1 and 2 make the new tria.
     7726        ElementMatrix* Ke=tria->CreateKMatrixBalancethickness();
     7727        delete tria->matice; delete tria;
     7728
     7729        /*Delete Vx and Vy averaged*/
     7730        this->inputs->DeleteInput(VxAverageEnum);
     7731        this->inputs->DeleteInput(VyAverageEnum);
     7732
     7733        /*clean up and return*/
     7734        return Ke;
     7735}
     7736/*}}}*/
     7737/*FUNCTION Penta::CreatePVectorBalancethickness {{{1*/
     7738ElementVector* Penta::CreatePVectorBalancethickness(void){
     7739
     7740        if (!IsOnBed()) return NULL;
     7741
     7742        /*Depth Averaging Vx and Vy*/
     7743        this->InputDepthAverageAtBase(VxEnum,VxAverageEnum);
     7744        this->InputDepthAverageAtBase(VyEnum,VyAverageEnum);
     7745
     7746        /*Call Tria function*/
     7747        Tria* tria=(Tria*)SpawnTria(0,1,2); //nodes 0, 1 and 2 make the new tria.
     7748        ElementVector* pe=tria->CreatePVectorBalancethickness();
     7749        delete tria->matice; delete tria;
     7750
     7751        /*Delete Vx and Vy averaged*/
     7752        this->inputs->DeleteInput(VxAverageEnum);
     7753        this->inputs->DeleteInput(VyAverageEnum);
     7754
     7755        /*Clean up and return*/
     7756        return pe;
     7757}
     7758/*}}}*/
     7759#endif
     7760
  • issm/trunk/src/c/objects/Elements/Penta.h

    r9761 r9775  
    8989                double GetZcoord(GaussPenta* gauss);
    9090                void   GetVectorFromInputs(Vec vector,int NameEnum);
    91                 #ifdef _HAVE_CONTROL_
    92                 double DragCoefficientAbsGradient(bool process_units,int weight_index);
    93                 void   Gradj(Vec gradient,int control_type);
    94                 void   GradjDragMacAyeal(Vec gradient);
    95                 void   GradjDragPattyn(Vec gradient);
    96                 void   GradjDragStokes(Vec gradient);
    97                 void   GradjBbarMacAyeal(Vec gradient);
    98                 void   GradjBbarPattyn(Vec gradient);
    99                 void   GradjBbarStokes(Vec gradient);
    100                 void   ControlInputGetGradient(Vec gradient,int enum_type);
    101                 void   ControlInputScaleGradient(int enum_type,double scale);
    102                 void   ControlInputSetGradient(double* gradient,int enum_type);
    103                 double RheologyBbarAbsGradient(bool process_units,int weight_index);
    104                 double ThicknessAbsMisfit(     bool process_units,int weight_index);
    105                 double SurfaceAbsVelMisfit(    bool process_units,int weight_index);
    106                 double SurfaceRelVelMisfit(    bool process_units,int weight_index);
    107                 double SurfaceLogVelMisfit(    bool process_units,int weight_index);
    108                 double SurfaceLogVxVyMisfit(   bool process_units,int weight_index);
    109                 double SurfaceAverageVelMisfit(bool process_units,int weight_index);
    110                 double ThicknessAbsGradient(bool process_units,int weight_index);
    111                 void   InputControlUpdate(double scalar,bool save_parameter);
    112                 #endif
     91               
    11392                int    Sid();
    11493                void   InputArtificialNoise(int enum_type,double min, double max);
     
    152131                void   ViscousHeatingCreateInput(void);
    153132                int    NodalValue(double* pvalue, int index, int natureofdataenum,bool process_units);
     133
     134                #ifdef _HAVE_CONTROL_
     135                double DragCoefficientAbsGradient(bool process_units,int weight_index);
     136                void   Gradj(Vec gradient,int control_type);
     137                void   GradjDragMacAyeal(Vec gradient);
     138                void   GradjDragPattyn(Vec gradient);
     139                void   GradjDragStokes(Vec gradient);
     140                void   GradjBbarMacAyeal(Vec gradient);
     141                void   GradjBbarPattyn(Vec gradient);
     142                void   GradjBbarStokes(Vec gradient);
     143                void   ControlInputGetGradient(Vec gradient,int enum_type);
     144                void   ControlInputScaleGradient(int enum_type,double scale);
     145                void   ControlInputSetGradient(double* gradient,int enum_type);
     146                double RheologyBbarAbsGradient(bool process_units,int weight_index);
     147                double ThicknessAbsMisfit(     bool process_units,int weight_index);
     148                double SurfaceAbsVelMisfit(    bool process_units,int weight_index);
     149                double SurfaceRelVelMisfit(    bool process_units,int weight_index);
     150                double SurfaceLogVelMisfit(    bool process_units,int weight_index);
     151                double SurfaceLogVxVyMisfit(   bool process_units,int weight_index);
     152                double SurfaceAverageVelMisfit(bool process_units,int weight_index);
     153                double ThicknessAbsGradient(bool process_units,int weight_index);
     154                void   InputControlUpdate(double scalar,bool save_parameter);
     155                #endif
    154156                /*}}}*/
    155157                /*Penta specific routines:{{{1*/
    156158                void      BedNormal(double* bed_normal, double xyz_list[3][3]);
    157                 ElementMatrix* CreateKMatrixBalancethickness(void);
     159                ElementMatrix* CreateKMatrixPrognostic(void);
     160                ElementMatrix* CreateKMatrixSlope(void);
     161                ElementVector* CreatePVectorPrognostic(void);
     162                ElementVector* CreatePVectorSlope(void);
     163                void      GetDofList(int** pdoflist,int approximation_enum,int setenum);
     164                void      GetDofList1(int* doflist);
     165                void      GetSidList(int* sidlist);
     166                int     GetElementType(void);
     167                void    GetParameterListOnVertices(double* pvalue,int enumtype);
     168                void    GetParameterListOnVertices(double* pvalue,int enumtype,double defaultvalue);
     169                void    GetParameterValue(double* pvalue,Node* node,int enumtype);
     170                void      GetPhi(double* phi, double*  epsilon, double viscosity);
     171                void      GetSolutionFromInputsEnthalpy(Vec solutiong);
     172                double GetStabilizationParameter(double u, double v, double w, double diameter, double rho_ice, double heatcapacity, double thermalconductivity);
     173                void    GetStrainRate3dPattyn(double* epsilon,double* xyz_list, GaussPenta* gauss, Input* vx_input, Input* vy_input);
     174                void    GetStrainRate3d(double* epsilon,double* xyz_list, GaussPenta* gauss, Input* vx_input, Input* vy_input, Input* vz_input);
     175                Penta*  GetUpperElement(void);
     176                Penta*  GetLowerElement(void);
     177                Penta*  GetBasalElement(void);
     178                void      InputExtrude(int enum_type,int object_type);
     179                void    InputUpdateFromSolutionPrognostic(double* solutiong);
     180                void    InputUpdateFromSolutionOneDof(double* solutiong,int enum_type);
     181                void    InputUpdateFromSolutionOneDofCollapsed(double* solutiong,int enum_type);
     182                bool      IsInput(int name);
     183                bool      IsOnSurface(void);
     184                bool      IsOnBed(void);
     185                bool    IsOnShelf(void);
     186                bool    IsNodeOnShelf(void);
     187                bool    IsNodeOnShelfFromFlags(double* flags);
     188                bool    IsOnWater(void);
     189                double  MinEdgeLength(double xyz_list[6][3]);
     190                void      ReduceMatrixStokes(double* Ke_reduced, double* Ke_temp);
     191                void      ReduceVectorStokes(double* Pe_reduced, double* Ke_temp, double* Pe_temp);
     192                void      SetClone(int* minranks);
     193                Tria*     SpawnTria(int g0, int g1, int g2);
     194                void      SurfaceNormal(double* surface_normal, double xyz_list[3][3]);
     195
     196                #ifdef _HAVE_DIAGNOSTIC_
    158197                ElementMatrix* CreateKMatrixCouplingMacAyealPattyn(void);
    159198                ElementMatrix* CreateKMatrixCouplingMacAyealPattynViscous(void);
     
    183222                ElementMatrix* CreateKMatrixDiagnosticVertVolume(void);
    184223                ElementMatrix* CreateKMatrixDiagnosticVertSurface(void);
    185                 ElementMatrix* CreateKMatrixEnthalpy(void);
    186                 ElementMatrix* CreateKMatrixEnthalpyVolume(void);
    187                 ElementMatrix* CreateKMatrixEnthalpyShelf(void);
    188                 ElementMatrix* CreateKMatrixMelting(void);
    189                 ElementMatrix* CreateKMatrixPrognostic(void);
    190                 ElementMatrix* CreateKMatrixSlope(void);
    191                 ElementMatrix* CreateKMatrixThermal(void);
    192                 ElementMatrix* CreateKMatrixThermalVolume(void);
    193                 ElementMatrix* CreateKMatrixThermalShelf(void);
    194                 ElementVector* CreatePVectorBalancethickness(void);
    195                 ElementVector* CreatePVectorAdjointHoriz(void);
    196                 ElementVector* CreatePVectorAdjointMacAyeal(void);
    197                 ElementVector* CreatePVectorAdjointPattyn(void);
     224                void           InputUpdateFromSolutionDiagnosticHoriz( double* solutiong);
     225                void           InputUpdateFromSolutionDiagnosticMacAyeal( double* solutiong);
     226                void           InputUpdateFromSolutionDiagnosticMacAyealPattyn( double* solutiong);
     227                void           InputUpdateFromSolutionDiagnosticMacAyealStokes( double* solutiong);
     228                void           InputUpdateFromSolutionDiagnosticPattyn( double* solutiong);
     229                void           InputUpdateFromSolutionDiagnosticPattynStokes( double* solutiong);
     230                void           InputUpdateFromSolutionDiagnosticHutter( double* solutiong);
     231                void           InputUpdateFromSolutionDiagnosticVert( double* solutiong);
     232                void           InputUpdateFromSolutionDiagnosticStokes( double* solutiong);
     233                void           GetSolutionFromInputsDiagnosticHoriz(Vec solutiong);
     234                void           GetSolutionFromInputsDiagnosticHutter(Vec solutiong);
     235                void           GetSolutionFromInputsDiagnosticStokes(Vec solutiong);
     236                void           GetSolutionFromInputsDiagnosticVert(Vec solutiong);
    198237                ElementVector* CreatePVectorCouplingMacAyealStokes(void);
    199238                ElementVector* CreatePVectorCouplingMacAyealStokesViscous(void);
     
    212251                ElementVector* CreatePVectorDiagnosticStokesViscous(void);
    213252                ElementVector* CreatePVectorDiagnosticStokesShelf(void);
     253                ElementVector* CreatePVectorDiagnosticVert(void);
     254                ElementVector* CreatePVectorDiagnosticVertVolume(void);
     255                ElementVector* CreatePVectorDiagnosticVertBase(void);
     256                #endif
     257
     258                #ifdef _HAVE_CONTROL_
     259                ElementVector* CreatePVectorAdjointHoriz(void);
     260                ElementVector* CreatePVectorAdjointMacAyeal(void);
     261                ElementVector* CreatePVectorAdjointPattyn(void);
     262                ElementVector* CreatePVectorAdjointStokes(void);
     263                void    InputUpdateFromSolutionAdjointHoriz( double* solutiong);
     264                void    InputUpdateFromSolutionAdjointStokes( double* solutiong);
     265                #endif
     266
     267                #ifdef _HAVE_HYDROLOGY_
     268                void    CreateHydrologyWaterVelocityInput(void);
     269                #endif
     270                #ifdef _HAVE_THERMAL_
     271                ElementMatrix* CreateKMatrixEnthalpy(void);
     272                ElementMatrix* CreateKMatrixEnthalpyVolume(void);
     273                ElementMatrix* CreateKMatrixEnthalpyShelf(void);
     274                ElementMatrix* CreateKMatrixThermal(void);
     275                ElementMatrix* CreateKMatrixMelting(void);
     276                ElementMatrix* CreateKMatrixThermalVolume(void);
     277                ElementMatrix* CreateKMatrixThermalShelf(void);
    214278                ElementVector* CreatePVectorEnthalpy(void);
    215279                ElementVector* CreatePVectorEnthalpyVolume(void);
    216280                ElementVector* CreatePVectorEnthalpyShelf(void);
    217281                ElementVector* CreatePVectorEnthalpySheet(void);
    218                 ElementVector* CreatePVectorAdjointStokes(void);
    219                 ElementVector* CreatePVectorDiagnosticVert(void);
    220                 ElementVector* CreatePVectorDiagnosticVertVolume(void);
    221                 ElementVector* CreatePVectorDiagnosticVertBase(void);
    222282                ElementVector* CreatePVectorMelting(void);
    223                 ElementVector* CreatePVectorPrognostic(void);
    224                 ElementVector* CreatePVectorSlope(void);
    225283                ElementVector* CreatePVectorThermal(void);
    226284                ElementVector* CreatePVectorThermalVolume(void);
    227285                ElementVector* CreatePVectorThermalShelf(void);
    228286                ElementVector* CreatePVectorThermalSheet(void);
    229                 void      GetDofList(int** pdoflist,int approximation_enum,int setenum);
    230                 void      GetDofList1(int* doflist);
    231                 void      GetSidList(int* sidlist);
    232                 int     GetElementType(void);
    233                 void    GetParameterListOnVertices(double* pvalue,int enumtype);
    234                 void    GetParameterListOnVertices(double* pvalue,int enumtype,double defaultvalue);
    235                 void    GetParameterValue(double* pvalue,Node* node,int enumtype);
    236                 void      GetPhi(double* phi, double*  epsilon, double viscosity);
    237                 void      GetSolutionFromInputsDiagnosticHoriz(Vec solutiong);
    238                 void      GetSolutionFromInputsDiagnosticHutter(Vec solutiong);
    239                 void      GetSolutionFromInputsDiagnosticStokes(Vec solutiong);
    240                 void      GetSolutionFromInputsDiagnosticVert(Vec solutiong);
    241                 void      GetSolutionFromInputsThermal(Vec solutiong);
    242                 void      GetSolutionFromInputsEnthalpy(Vec solutiong);
    243                 double GetStabilizationParameter(double u, double v, double w, double diameter, double rho_ice, double heatcapacity, double thermalconductivity);
    244                 void    GetStrainRate3dPattyn(double* epsilon,double* xyz_list, GaussPenta* gauss, Input* vx_input, Input* vy_input);
    245                 void    GetStrainRate3d(double* epsilon,double* xyz_list, GaussPenta* gauss, Input* vx_input, Input* vy_input, Input* vz_input);
    246                 Penta*  GetUpperElement(void);
    247                 Penta*  GetLowerElement(void);
    248                 Penta*  GetBasalElement(void);
    249                 void      InputExtrude(int enum_type,int object_type);
    250                 void    InputUpdateFromSolutionAdjointHoriz( double* solutiong);
    251                 void    InputUpdateFromSolutionAdjointStokes( double* solutiong);
    252                 void    InputUpdateFromSolutionDiagnosticHoriz( double* solutiong);
    253                 void    InputUpdateFromSolutionDiagnosticMacAyeal( double* solutiong);
    254                 void    InputUpdateFromSolutionDiagnosticMacAyealPattyn( double* solutiong);
    255                 void    InputUpdateFromSolutionDiagnosticMacAyealStokes( double* solutiong);
    256                 void    InputUpdateFromSolutionDiagnosticPattyn( double* solutiong);
    257                 void    InputUpdateFromSolutionDiagnosticPattynStokes( double* solutiong);
    258                 void    InputUpdateFromSolutionDiagnosticHutter( double* solutiong);
    259                 void    InputUpdateFromSolutionDiagnosticVert( double* solutiong);
    260                 void    InputUpdateFromSolutionDiagnosticStokes( double* solutiong);
    261                 void    InputUpdateFromSolutionPrognostic(double* solutiong);
    262                 void    InputUpdateFromSolutionThermal( double* solutiong);
    263                 void    InputUpdateFromSolutionEnthalpy( double* solutiong);
    264                 void    InputUpdateFromSolutionOneDof(double* solutiong,int enum_type);
    265                 void    InputUpdateFromSolutionOneDofCollapsed(double* solutiong,int enum_type);
    266                 bool      IsInput(int name);
    267                 bool      IsOnSurface(void);
    268                 bool      IsOnBed(void);
    269                 bool    IsOnShelf(void);
    270                 bool    IsNodeOnShelf(void);
    271                 bool    IsNodeOnShelfFromFlags(double* flags);
    272                 bool    IsOnWater(void);
    273                 double  MinEdgeLength(double xyz_list[6][3]);
    274            void   ReduceMatrixStokes(double* Ke_reduced, double* Ke_temp);
    275                 void      ReduceVectorStokes(double* Pe_reduced, double* Ke_temp, double* Pe_temp);
    276                 void      SetClone(int* minranks);
    277                 Tria*     SpawnTria(int g0, int g1, int g2);
    278                 void      SurfaceNormal(double* surface_normal, double xyz_list[3][3]);
     287                void           GetSolutionFromInputsThermal(Vec solutiong);
     288                void           InputUpdateFromSolutionThermal( double* solutiong);
     289                void           InputUpdateFromSolutionEnthalpy( double* solutiong);
     290                #endif
     291                #ifdef _HAVE_BALANCED_
     292                ElementMatrix* CreateKMatrixBalancethickness(void);
     293                ElementVector* CreatePVectorBalancethickness(void);
     294                #endif
    279295                /*}}}*/
    280296};
  • issm/trunk/src/c/objects/Elements/Tria.cpp

    r9761 r9775  
    376376}
    377377/*}}}*/
    378 /*FUNCTION Tria::CreateHydrologyWaterVelocityInput {{{1*/
    379 void Tria::CreateHydrologyWaterVelocityInput(void){
    380 
    381         /*material parameters: */
    382         double mu_water=0.001787;  //unit= [N s/m2]
    383         double w;
    384         double rho_ice, rho_water, g;
    385         double dsdx,dsdy,dbdx,dbdy;
    386         double vx[NUMVERTICES];
    387         double vy[NUMVERTICES];
    388         GaussTria *gauss = NULL;
    389 
    390         /*Retrieve all inputs and parameters*/
    391         rho_ice=matpar->GetRhoIce();
    392         rho_water=matpar->GetRhoWater();
    393         g=matpar->GetG();
    394         Input* surfaceslopex_input=inputs->GetInput(SurfaceSlopeXEnum); _assert_(surfaceslopex_input);
    395         Input* surfaceslopey_input=inputs->GetInput(SurfaceSlopeYEnum); _assert_(surfaceslopey_input);
    396         Input* bedslopex_input=inputs->GetInput(BedSlopeXEnum);         _assert_(bedslopex_input);
    397         Input* bedslopey_input=inputs->GetInput(BedSlopeYEnum);         _assert_(bedslopey_input);
    398         Input* watercolumn_input=inputs->GetInput(WatercolumnEnum);     _assert_(watercolumn_input);
    399 
    400         gauss=new GaussTria();
    401         for (int iv=0;iv<NUMVERTICES;iv++){
    402                 gauss->GaussVertex(iv);
    403                 surfaceslopex_input->GetParameterValue(&dsdx,gauss);
    404                 surfaceslopey_input->GetParameterValue(&dsdy,gauss);
    405                 bedslopex_input->GetParameterValue(&dbdx,gauss);
    406                 bedslopey_input->GetParameterValue(&dbdy,gauss);
    407                 watercolumn_input->GetParameterValue(&w,gauss);
    408 
    409                 /* Water velocity x and y components */
    410                 vx[iv]= - pow(w,2)/(12 * mu_water)*(rho_ice*g*dsdx+(rho_water-rho_ice)*g*dbdx);
    411                 vy[iv]= - pow(w,2)/(12 * mu_water)*(rho_ice*g*dsdy+(rho_water-rho_ice)*g*dbdy);
    412                 //vx[iv]=0.001;
    413                 //vy[iv]=0;
    414         }
    415 
    416         /*clean-up*/
    417         delete gauss;
    418 
    419         /*Add to inputs*/
    420         this->inputs->AddInput(new TriaVertexInput(HydrologyWaterVxEnum,vx));
    421         this->inputs->AddInput(new TriaVertexInput(HydrologyWaterVyEnum,vy));
    422 }
    423 /*}}}*/
    424378/*FUNCTION Tria::CreateKMatrix {{{1*/
    425379void  Tria::CreateKMatrix(Mat Kff, Mat Kfs,Vec df){
     
    439393        /*Just branch to the correct element stiffness matrix generator, according to the type of analysis we are carrying out: */
    440394        switch(analysis_type){
     395                #ifdef _HAVE_DIAGNOSTIC_
    441396                case DiagnosticHorizAnalysisEnum: case AdjointHorizAnalysisEnum:
    442397                        Ke=CreateKMatrixDiagnosticMacAyeal();
     
    445400                        Ke=CreateKMatrixDiagnosticHutter();
    446401                        break;
     402                 #endif
    447403                case BedSlopeXAnalysisEnum: case SurfaceSlopeXAnalysisEnum: case BedSlopeYAnalysisEnum: case SurfaceSlopeYAnalysisEnum:
    448404                        Ke=CreateKMatrixSlope();
     
    451407                        Ke=CreateKMatrixPrognostic();
    452408                        break;
     409                #ifdef _HAVE_HYDROLOGY_
    453410                case HydrologyAnalysisEnum:
    454411                        Ke=CreateKMatrixHydrology();
    455412                        break;
     413                #endif
     414                #ifdef _HAVE_BALANCED_
    456415                case BalancethicknessAnalysisEnum:
    457416                        Ke=CreateKMatrixBalancethickness();
    458417                        break;
     418                #endif
     419                #ifdef _HAVE_CONTROL_
    459420                case AdjointBalancethicknessAnalysisEnum:
    460421                        Ke=CreateKMatrixAdjointBalancethickness();
    461422                        break;
     423                #endif
    462424                default:
    463425                        _error_("analysis %i (%s) not supported yet",analysis_type,EnumToStringx(analysis_type));
     
    469431                delete Ke;
    470432        }
    471 }
    472 /*}}}*/
    473 /*FUNCTION Tria::CreateKMatrixAdjointBalancethickness {{{1*/
    474 ElementMatrix* Tria::CreateKMatrixAdjointBalancethickness(void){
    475 
    476         ElementMatrix* Ke=NULL;
    477 
    478         /*Get Element Matrix of the forward model*/
    479         switch(GetElementType()){
    480                 case P1Enum:
    481                         Ke=CreateKMatrixBalancethickness_CG();
    482                         break;
    483                 case P1DGEnum:
    484                         Ke=CreateKMatrixBalancethickness_DG();
    485                         break;
    486                 default:
    487                         _error_("Element type %s not supported yet",EnumToStringx(GetElementType()));
    488         }
    489 
    490         /*Transpose and return Ke*/
    491         Ke->Transpose();
    492         return Ke;
    493 }
    494 /*}}}*/
    495 /*FUNCTION Tria::CreateKMatrixBalancethickness {{{1*/
    496 ElementMatrix* Tria::CreateKMatrixBalancethickness(void){
    497 
    498         switch(GetElementType()){
    499                 case P1Enum:
    500                         return CreateKMatrixBalancethickness_CG();
    501                 case P1DGEnum:
    502                         return CreateKMatrixBalancethickness_DG();
    503                 default:
    504                         _error_("Element type %s not supported yet",EnumToStringx(GetElementType()));
    505         }
    506 
    507 }
    508 /*}}}*/
    509 /*FUNCTION Tria::CreateKMatrixBalancethickness_CG {{{1*/
    510 ElementMatrix* Tria::CreateKMatrixBalancethickness_CG(void){
    511 
    512         /*Constants*/
    513         const int    numdof=NDOF1*NUMVERTICES;
    514 
    515         /*Intermediaries */
    516         int        stabilization;
    517         int        i,j,ig,dim;
    518         double     Jdettria,vx,vy,dvxdx,dvydy,vel,h;
    519         double     dvx[2],dvy[2];
    520         double     xyz_list[NUMVERTICES][3];
    521         double     L[NUMVERTICES];
    522         double     B[2][NUMVERTICES];
    523         double     Bprime[2][NUMVERTICES];
    524         double     K[2][2]                          = {0.0};
    525         double     KDL[2][2]                        = {0.0};
    526         double     DL[2][2]                         = {0.0};
    527         double     DLprime[2][2]                    = {0.0};
    528         double     DL_scalar;
    529         GaussTria *gauss                            = NULL;
    530 
    531         /*Initialize Element matrix*/
    532         ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,NoneApproximationEnum);
    533 
    534         /*Retrieve all Inputs and parameters: */
    535         GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
    536         this->parameters->FindParam(&stabilization,BalancethicknessStabilizationEnum);
    537         this->parameters->FindParam(&dim,MeshDimensionEnum);
    538         Input* vxaverage_input=NULL;
    539         Input* vyaverage_input=NULL;
    540         if(dim==2){
    541                 vxaverage_input=inputs->GetInput(VxEnum); _assert_(vxaverage_input);
    542                 vyaverage_input=inputs->GetInput(VyEnum); _assert_(vyaverage_input);
    543         }
    544         else{
    545                 vxaverage_input=inputs->GetInput(VxAverageEnum); _assert_(vxaverage_input);
    546                 vyaverage_input=inputs->GetInput(VyAverageEnum); _assert_(vyaverage_input);
    547         }
    548         h=sqrt(2*this->GetArea());
    549 
    550         ///*Create Artificial diffusivity once for all if requested*/
    551         //if(stabilization){
    552         //      gauss=new GaussTria();
    553         //      gauss->GaussCenter();
    554         //      GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss);
    555         //      delete gauss;
    556 
    557         //      vxaverage_input->GetParameterAverage(&vx);
    558         //      vyaverage_input->GetParameterAverage(&vy);
    559         //      K[0][0]=pow(Jdettria,(double).5)/2.0*fabs(vx);
    560         //      K[1][1]=pow(Jdettria,(double).5)/2.0*fabs(vy);
    561         //}
    562 
    563         /*Start looping on the number of gaussian points:*/
    564         gauss=new GaussTria(2);
    565         for (ig=gauss->begin();ig<gauss->end();ig++){
    566 
    567                 gauss->GaussPoint(ig);
    568 
    569                 GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss);
    570                 GetBPrognostic(&B[0][0], &xyz_list[0][0], gauss);
    571                 GetBprimePrognostic(&Bprime[0][0], &xyz_list[0][0], gauss);
    572 
    573                 vxaverage_input->GetParameterValue(&vx,gauss);
    574                 vyaverage_input->GetParameterValue(&vy,gauss);
    575                 vxaverage_input->GetParameterDerivativeValue(&dvx[0],&xyz_list[0][0],gauss);
    576                 vyaverage_input->GetParameterDerivativeValue(&dvy[0],&xyz_list[0][0],gauss);
    577 
    578                 dvxdx=dvx[0];
    579                 dvydy=dvy[1];
    580                 DL_scalar=gauss->weight*Jdettria;
    581 
    582                 DL[0][0]=DL_scalar*dvxdx;
    583                 DL[1][1]=DL_scalar*dvydy;
    584 
    585                 DLprime[0][0]=DL_scalar*vx;
    586                 DLprime[1][1]=DL_scalar*vy;
    587 
    588                 TripleMultiply( &B[0][0],2,numdof,1,
    589                                         &DL[0][0],2,2,0,
    590                                         &B[0][0],2,numdof,0,
    591                                         &Ke->values[0],1);
    592 
    593                 TripleMultiply( &B[0][0],2,numdof,1,
    594                                         &DLprime[0][0],2,2,0,
    595                                         &Bprime[0][0],2,numdof,0,
    596                                         &Ke->values[0],1);
    597 
    598                 if(stabilization==1){
    599                         vel=sqrt(pow(vx,2.)+pow(vy,2.));
    600                         K[0][0]=h/(2*vel)*vx*vx;
    601                         K[1][0]=h/(2*vel)*vy*vx;
    602                         K[0][1]=h/(2*vel)*vx*vy;
    603                         K[1][1]=h/(2*vel)*vy*vy;
    604                         KDL[0][0]=DL_scalar*K[0][0];
    605                         KDL[1][0]=DL_scalar*K[1][0];
    606                         KDL[0][1]=DL_scalar*K[0][1];
    607                         KDL[1][1]=DL_scalar*K[1][1];
    608 
    609                         //KDL[0][0]=DL_scalar*K[0][0];
    610                         //KDL[1][1]=DL_scalar*K[1][1];
    611 
    612                         TripleMultiply( &Bprime[0][0],2,numdof,1,
    613                                                 &KDL[0][0],2,2,0,
    614                                                 &Bprime[0][0],2,numdof,0,
    615                                                 &Ke->values[0],1);
    616                 }
    617         }
    618 
    619         /*Clean up and return*/
    620         delete gauss;
    621         return Ke;
    622 }
    623 /*}}}*/
    624 /*FUNCTION Tria::CreateKMatrixBalancethickness_DG {{{1*/
    625 ElementMatrix* Tria::CreateKMatrixBalancethickness_DG(void){
    626 
    627         /*Constants*/
    628         const int  numdof=NDOF1*NUMVERTICES;
    629 
    630         /*Intermediaries*/
    631         int        i,j,ig,dim;
    632         double     vx,vy,Jdettria;
    633         double     xyz_list[NUMVERTICES][3];
    634         double     B[2][NUMVERTICES];
    635         double     Bprime[2][NUMVERTICES];
    636         double     DL[2][2]={0.0};
    637         double     DL_scalar;
    638         GaussTria  *gauss=NULL;
    639 
    640         /*Initialize Element matrix*/
    641         ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,NoneApproximationEnum);
    642 
    643         /*Retrieve all inputs and parameters*/
    644         GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
    645         this->parameters->FindParam(&dim,MeshDimensionEnum);
    646         Input* vx_input=inputs->GetInput(VxEnum); _assert_(vx_input);
    647         Input* vy_input=inputs->GetInput(VyEnum); _assert_(vy_input);
    648 
    649         /*Start looping on the number of gaussian points:*/
    650         gauss=new GaussTria(2);
    651         for (ig=gauss->begin();ig<gauss->end();ig++){
    652 
    653                 gauss->GaussPoint(ig);
    654 
    655                 GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss);
    656                 /*WARNING: B and Bprime are inverted compared to usual prognostic!!!!*/
    657                 GetBPrognostic(&Bprime[0][0], &xyz_list[0][0], gauss);
    658                 GetBprimePrognostic(&B[0][0], &xyz_list[0][0], gauss);
    659 
    660                 vx_input->GetParameterValue(&vx,gauss);
    661                 vy_input->GetParameterValue(&vy,gauss);
    662 
    663                 DL_scalar=-gauss->weight*Jdettria;
    664                 DL[0][0]=DL_scalar*vx;
    665                 DL[1][1]=DL_scalar*vy;
    666 
    667                 TripleMultiply( &B[0][0],2,numdof,1,
    668                                         &DL[0][0],2,2,0,
    669                                         &Bprime[0][0],2,numdof,0,
    670                                         &Ke->values[0],1);
    671         }
    672 
    673         /*Clean up and return*/
    674         delete gauss;
    675         return Ke;
    676 }
    677 /*}}}*/
    678 /*FUNCTION Tria::CreateKMatrixDiagnosticMacAyeal {{{1*/
    679 ElementMatrix* Tria::CreateKMatrixDiagnosticMacAyeal(void){
    680 
    681         /*compute all stiffness matrices for this element*/
    682         ElementMatrix* Ke1=CreateKMatrixDiagnosticMacAyealViscous();
    683         ElementMatrix* Ke2=CreateKMatrixDiagnosticMacAyealFriction();
    684         ElementMatrix* Ke =new ElementMatrix(Ke1,Ke2);
    685        
    686         /*clean-up and return*/
    687         delete Ke1;
    688         delete Ke2;
    689         return Ke;
    690 }
    691 /*}}}*/
    692 /*FUNCTION Tria::CreateKMatrixDiagnosticMacAyealViscous{{{1*/
    693 ElementMatrix* Tria::CreateKMatrixDiagnosticMacAyealViscous(void){
    694 
    695         /*Constants*/
    696         const int  numdof=NDOF2*NUMVERTICES;
    697 
    698         /*Intermediaries*/
    699         int        i,j,ig;
    700         double     xyz_list[NUMVERTICES][3];
    701         double     viscosity,newviscosity,oldviscosity;
    702         double     viscosity_overshoot,thickness,Jdet;
    703         double     epsilon[3],oldepsilon[3];    /* epsilon=[exx,eyy,exy];    */
    704         double     B[3][numdof];
    705         double     Bprime[3][numdof];
    706         double     D[3][3]   = {0.0};
    707         double     D_scalar;
    708         GaussTria *gauss = NULL;
    709 
    710         /*Initialize Element matrix*/
    711         ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,MacAyealApproximationEnum);
    712 
    713         /*Retrieve all inputs and parameters*/
    714         GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
    715         Input* thickness_input=inputs->GetInput(ThicknessEnum); _assert_(thickness_input);
    716         Input* vx_input=inputs->GetInput(VxEnum);               _assert_(vx_input);
    717         Input* vy_input=inputs->GetInput(VyEnum);               _assert_(vy_input);
    718         Input* vxold_input=inputs->GetInput(VxPicardEnum);      _assert_(vxold_input);
    719         Input* vyold_input=inputs->GetInput(VyPicardEnum);      _assert_(vyold_input);
    720         this->parameters->FindParam(&viscosity_overshoot,DiagnosticViscosityOvershootEnum);
    721 
    722         /* Start  looping on the number of gaussian points: */
    723         gauss=new GaussTria(2);
    724         for (ig=gauss->begin();ig<gauss->end();ig++){
    725 
    726                 gauss->GaussPoint(ig);
    727 
    728                 GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0],gauss);
    729                 GetBMacAyeal(&B[0][0], &xyz_list[0][0], gauss);
    730                 GetBprimeMacAyeal(&Bprime[0][0], &xyz_list[0][0], gauss);
    731 
    732                 this->GetStrainRate2d(&epsilon[0],&xyz_list[0][0],gauss,vx_input,vy_input);
    733                 this->GetStrainRate2d(&oldepsilon[0],&xyz_list[0][0],gauss,vxold_input,vyold_input);
    734                 matice->GetViscosity2d(&viscosity, &epsilon[0]);
    735                 matice->GetViscosity2d(&oldviscosity, &oldepsilon[0]);
    736                 thickness_input->GetParameterValue(&thickness, gauss);
    737 
    738                 newviscosity=viscosity+viscosity_overshoot*(viscosity-oldviscosity);
    739                 D_scalar=2*newviscosity*thickness*gauss->weight*Jdet;
    740                 for (i=0;i<3;i++) D[i][i]=D_scalar;
    741 
    742                 TripleMultiply(&B[0][0],3,numdof,1,
    743                                         &D[0][0],3,3,0,
    744                                         &Bprime[0][0],3,numdof,0,
    745                                         &Ke->values[0],1);
    746         }
    747 
    748         /*Clean up and return*/
    749         delete gauss;
    750         return Ke;
    751 }
    752 /*}}}*/
    753 /*FUNCTION Tria::CreateKMatrixDiagnosticMacAyealFriction {{{1*/
    754 ElementMatrix* Tria::CreateKMatrixDiagnosticMacAyealFriction(void){
    755 
    756         /*Constants*/
    757         const int  numdof=NDOF2*NUMVERTICES;
    758 
    759         /*Intermediaries*/
    760         int        i,j,ig;
    761         int        analysis_type;
    762         double     MAXSLOPE  = .06; // 6 %
    763         double     MOUNTAINKEXPONENT = 10;
    764         double     slope_magnitude,alpha2;
    765         double     Jdet;
    766         double     L[2][numdof];
    767         double     DL[2][2]  = {{ 0,0 },{0,0}};
    768         double     DL_scalar;
    769         double     slope[2]  = {0.0,0.0};
    770         double     xyz_list[NUMVERTICES][3];
    771         Friction  *friction = NULL;
    772         GaussTria *gauss    = NULL;
    773 
    774         /*Initialize Element matrix and return if necessary*/
    775         if(IsOnShelf()) return NULL;
    776         ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,MacAyealApproximationEnum);
    777 
    778         /*Retrieve all inputs and parameters*/
    779         GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
    780         Input* surface_input=inputs->GetInput(SurfaceEnum); _assert_(surface_input);
    781         Input* vx_input=inputs->GetInput(VxEnum);           _assert_(vx_input);
    782         Input* vy_input=inputs->GetInput(VyEnum);           _assert_(vy_input);
    783         Input* vz_input=inputs->GetInput(VzEnum);           _assert_(vz_input);
    784         parameters->FindParam(&analysis_type,AnalysisTypeEnum);
    785 
    786         /*build friction object, used later on: */
    787         friction=new Friction("2d",inputs,matpar,analysis_type);
    788 
    789         /* Start  looping on the number of gaussian points: */
    790         gauss=new GaussTria(2);
    791         for (ig=gauss->begin();ig<gauss->end();ig++){
    792 
    793                 gauss->GaussPoint(ig);
    794 
    795                 // If we have a slope > 6% for this element,  it means  we are on a mountain. In this particular case,
    796                 //velocity should be = 0. To achieve this result, we set alpha2_list to a very high value: */
    797                 surface_input->GetParameterDerivativeValue(&slope[0],&xyz_list[0][0],gauss);
    798                 slope_magnitude=sqrt(pow(slope[0],2)+pow(slope[1],2));
    799                 if(slope_magnitude>MAXSLOPE) alpha2=pow((double)10,MOUNTAINKEXPONENT);
    800                 else friction->GetAlpha2(&alpha2, gauss,VxEnum,VyEnum,VzEnum);
    801 
    802                 GetL(&L[0][0], &xyz_list[0][0], gauss,NDOF2);
    803                 GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0],gauss);
    804                 DL_scalar=alpha2*gauss->weight*Jdet;
    805                 for (i=0;i<2;i++) DL[i][i]=DL_scalar;
    806                
    807                 TripleMultiply( &L[0][0],2,numdof,1,
    808                                         &DL[0][0],2,2,0,
    809                                         &L[0][0],2,numdof,0,
    810                                         &Ke->values[0],1);
    811         }
    812 
    813         /*Clean up and return*/
    814         delete gauss;
    815         delete friction;
    816         return Ke;
    817 }
    818 /*}}}*/
    819 /*FUNCTION Tria::CreateKMatrixDiagnosticHutter{{{1*/
    820 ElementMatrix* Tria::CreateKMatrixDiagnosticHutter(void){
    821 
    822         /*Intermediaries*/
    823         const int numdof=NUMVERTICES*NDOF2;
    824         int    i,connectivity;
    825 
    826         /*Initialize Element matrix*/
    827         ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,NoneApproximationEnum);
    828 
    829         /*Create Element matrix*/
    830         for(i=0;i<NUMVERTICES;i++){
    831                 connectivity=nodes[i]->GetConnectivity();
    832                 Ke->values[(2*i)*numdof  +(2*i)  ]=1/(double)connectivity;
    833                 Ke->values[(2*i+1)*numdof+(2*i+1)]=1/(double)connectivity;
    834         }
    835 
    836         /*Clean up and return*/
    837         return Ke;
    838 }
    839 /*}}}*/
    840 /*FUNCTION Tria::CreateKMatrixHydrology{{{1*/
    841 ElementMatrix* Tria::CreateKMatrixHydrology(void){
    842 
    843         /*Constants*/
    844         const int    numdof=NDOF1*NUMVERTICES;
    845 
    846         /*Intermediaries */
    847         int        artdiff;
    848         int        i,j,ig;
    849         double     Jdettria,DL_scalar,dt,h;
    850         double     vx,vy,vel,dvxdx,dvydy;
    851         double     dvx[2],dvy[2];
    852         double     v_gauss[2]={0.0};
    853         double     xyz_list[NUMVERTICES][3];
    854         double     L[NUMVERTICES];
    855         double     B[2][NUMVERTICES];
    856         double     Bprime[2][NUMVERTICES];
    857         double     K[2][2]                        ={0.0};
    858         double     KDL[2][2]                      ={0.0};
    859         double     DL[2][2]                        ={0.0};
    860         double     DLprime[2][2]                   ={0.0};
    861         GaussTria *gauss=NULL;
    862 
    863         /*Initialize Element matrix*/
    864         ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,NoneApproximationEnum);
    865 
    866         /*Create water velocity vx and vy from current inputs*/
    867         CreateHydrologyWaterVelocityInput();
    868 
    869         /*Retrieve all inputs and parameters*/
    870         GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
    871         this->parameters->FindParam(&dt,TimesteppingTimeStepEnum);
    872         this->parameters->FindParam(&artdiff,HydrologyStabilizationEnum);
    873         Input* vx_input=inputs->GetInput(HydrologyWaterVxEnum); _assert_(vx_input);
    874         Input* vy_input=inputs->GetInput(HydrologyWaterVyEnum); _assert_(vy_input);
    875         h=this->GetArea();
    876 
    877         /* Start  looping on the number of gaussian points: */
    878         gauss=new GaussTria(2);
    879         for (ig=gauss->begin();ig<gauss->end();ig++){
    880 
    881                 gauss->GaussPoint(ig);
    882 
    883                 GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss);
    884                 GetL(&L[0], &xyz_list[0][0], gauss,NDOF1);
    885 
    886                 vx_input->GetParameterValue(&vx,gauss);
    887                 vy_input->GetParameterValue(&vy,gauss);
    888                 vx_input->GetParameterDerivativeValue(&dvx[0],&xyz_list[0][0],gauss);
    889                 vy_input->GetParameterDerivativeValue(&dvy[0],&xyz_list[0][0],gauss);
    890 
    891                 DL_scalar=gauss->weight*Jdettria;
    892 
    893                 TripleMultiply( &L[0],1,numdof,1,
    894                                         &DL_scalar,1,1,0,
    895                                         &L[0],1,numdof,0,
    896                                         &Ke->values[0],1);
    897 
    898                 GetBPrognostic(&B[0][0], &xyz_list[0][0], gauss);
    899                 GetBprimePrognostic(&Bprime[0][0], &xyz_list[0][0], gauss);
    900 
    901                 dvxdx=dvx[0];
    902                 dvydy=dvy[1];
    903                 DL_scalar=dt*gauss->weight*Jdettria;
    904 
    905                 DL[0][0]=DL_scalar*dvxdx;
    906                 DL[1][1]=DL_scalar*dvydy;
    907                 DLprime[0][0]=DL_scalar*vx;
    908                 DLprime[1][1]=DL_scalar*vy;
    909 
    910                 TripleMultiply( &B[0][0],2,numdof,1,
    911                                         &DL[0][0],2,2,0,
    912                                         &B[0][0],2,numdof,0,
    913                                         &Ke->values[0],1);
    914 
    915                 TripleMultiply( &B[0][0],2,numdof,1,
    916                                         &DLprime[0][0],2,2,0,
    917                                         &Bprime[0][0],2,numdof,0,
    918                                         &Ke->values[0],1);
    919 
    920                 if(artdiff){
    921                         vel=sqrt(pow(vx,2.)+pow(vy,2.));
    922                         K[0][0]=h/(2*vel)*vx*vx;
    923                         K[1][0]=h/(2*vel)*vy*vx;
    924                         K[0][1]=h/(2*vel)*vx*vy;
    925                         K[1][1]=h/(2*vel)*vy*vy;
    926                         KDL[0][0]=DL_scalar*K[0][0];
    927                         KDL[1][0]=DL_scalar*K[1][0];
    928                         KDL[0][1]=DL_scalar*K[0][1];
    929                         KDL[1][1]=DL_scalar*K[1][1];
    930 
    931                         TripleMultiply( &Bprime[0][0],2,numdof,1,
    932                                                 &KDL[0][0],2,2,0,
    933                                                 &Bprime[0][0],2,numdof,0,
    934                                                 &Ke->values[0],1);
    935                 }
    936         }
    937 
    938         /*Clean up and return*/
    939         delete gauss;
    940         return Ke;
    941433}
    942434/*}}}*/
     
    1247739        /*Just branch to the correct load generator, according to the type of analysis we are carrying out: */
    1248740        switch(analysis_type){
     741                #ifdef _HAVE_DIAGNOSTIC_
    1249742                case DiagnosticHorizAnalysisEnum:
    1250743                        pe=CreatePVectorDiagnosticMacAyeal();
     
    1253746                        pe=CreatePVectorDiagnosticHutter();
    1254747                        break;
     748                #endif
    1255749                case BedSlopeXAnalysisEnum: case SurfaceSlopeXAnalysisEnum: case BedSlopeYAnalysisEnum: case SurfaceSlopeYAnalysisEnum:
    1256750                        pe=CreatePVectorSlope();
     
    1259753                        pe=CreatePVectorPrognostic();
    1260754                        break;
     755                #ifdef _HAVE_HYDROLOGY_
    1261756                case HydrologyAnalysisEnum:
    1262757                        pe=CreatePVectorHydrology();
    1263758                        break;
     759                #endif
     760                #ifdef _HAVE_BALANCED_
    1264761                case BalancethicknessAnalysisEnum:
    1265762                        pe=CreatePVectorBalancethickness();
    1266763                        break;
     764                #endif
    1267765                #ifdef _HAVE_CONTROL_
    1268766                case AdjointBalancethicknessAnalysisEnum:
     
    1284782}
    1285783/*}}}*/
    1286 /*FUNCTION Tria::CreatePVectorBalancethickness{{{1*/
    1287 ElementVector* Tria::CreatePVectorBalancethickness(void){
    1288 
    1289         switch(GetElementType()){
    1290                 case P1Enum:
    1291                         return CreatePVectorBalancethickness_CG();
    1292                         break;
    1293                 case P1DGEnum:
    1294                         return CreatePVectorBalancethickness_DG();
    1295                 default:
    1296                         _error_("Element type %s not supported yet",EnumToStringx(GetElementType()));
    1297         }
    1298 }
    1299 /*}}}*/
    1300 /*FUNCTION Tria::CreatePVectorBalancethickness_CG{{{1*/
    1301 ElementVector* Tria::CreatePVectorBalancethickness_CG(void){
    1302 
    1303         /*Constants*/
    1304         const int    numdof=NDOF1*NUMVERTICES;
    1305        
    1306         /*Intermediaries */
    1307         int        i,j,ig;
    1308         double     xyz_list[NUMVERTICES][3];
    1309         double     dhdt_g,basal_melting_g,surface_mass_balance_g,Jdettria;
    1310         double     L[NUMVERTICES];
    1311         GaussTria* gauss=NULL;
    1312 
    1313         /*Initialize Element vector*/
    1314         ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters);
    1315 
    1316         /*Retrieve all inputs and parameters*/
    1317         GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
    1318         Input* surface_mass_balance_input=inputs->GetInput(SurfaceforcingsMassBalanceEnum); _assert_(surface_mass_balance_input);
    1319         Input* basal_melting_input=inputs->GetInput(BasalforcingsMeltingRateEnum);          _assert_(basal_melting_input);
    1320         Input* dhdt_input=inputs->GetInput(BalancethicknessThickeningRateEnum);             _assert_(dhdt_input);
    1321        
    1322         /* Start  looping on the number of gaussian points: */
    1323         gauss=new GaussTria(2);
    1324         for(ig=gauss->begin();ig<gauss->end();ig++){
    1325 
    1326                 gauss->GaussPoint(ig);
    1327 
    1328                 surface_mass_balance_input->GetParameterValue(&surface_mass_balance_g,gauss);
    1329                 basal_melting_input->GetParameterValue(&basal_melting_g,gauss);
    1330                 dhdt_input->GetParameterValue(&dhdt_g,gauss);
    1331 
    1332                 GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss);
    1333                 GetL(&L[0], &xyz_list[0][0], gauss,NDOF1);
    1334 
    1335                 for(i=0;i<numdof;i++) pe->values[i]+=Jdettria*gauss->weight*(surface_mass_balance_g-basal_melting_g-dhdt_g)*L[i];
    1336         }
    1337 
    1338         /*Clean up and return*/
    1339         delete gauss;
    1340         return pe;
    1341 }
    1342 /*}}}*/
    1343 /*FUNCTION Tria::CreatePVectorBalancethickness_DG {{{1*/
    1344 ElementVector* Tria::CreatePVectorBalancethickness_DG(void){
    1345 
    1346         /*Constants*/
    1347         const int    numdof=NDOF1*NUMVERTICES;
    1348 
    1349         /*Intermediaries */
    1350         int        i,j,ig;
    1351         double     xyz_list[NUMVERTICES][3];
    1352         double     basal_melting_g,surface_mass_balance_g,dhdt_g,Jdettria;
    1353         double     L[NUMVERTICES];
    1354         GaussTria* gauss=NULL;
    1355 
    1356         /*Initialize Element vector*/
    1357         ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters);
    1358 
    1359         /*Retrieve all inputs and parameters*/
    1360         GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
    1361         Input* surface_mass_balance_input=inputs->GetInput(SurfaceforcingsMassBalanceEnum); _assert_(surface_mass_balance_input);
    1362         Input* basal_melting_input=inputs->GetInput(BasalforcingsMeltingRateEnum);          _assert_(basal_melting_input);
    1363         Input* dhdt_input=inputs->GetInput(BalancethicknessThickeningRateEnum);                                       _assert_(dhdt_input);
    1364 
    1365         /* Start  looping on the number of gaussian points: */
    1366         gauss=new GaussTria(2);
    1367         for(ig=gauss->begin();ig<gauss->end();ig++){
    1368 
    1369                 gauss->GaussPoint(ig);
    1370 
    1371                 surface_mass_balance_input->GetParameterValue(&surface_mass_balance_g,gauss);
    1372                 basal_melting_input->GetParameterValue(&basal_melting_g,gauss);
    1373                 dhdt_input->GetParameterValue(&dhdt_g,gauss);
    1374 
    1375                 GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss);
    1376                 GetL(&L[0], &xyz_list[0][0], gauss,NDOF1);
    1377 
    1378                 for(i=0;i<numdof;i++) pe->values[i]+=Jdettria*gauss->weight*(surface_mass_balance_g-basal_melting_g-dhdt_g)*L[i];
    1379         }
    1380 
    1381         /*Clean up and return*/
    1382         delete gauss;
    1383         return pe;
    1384 }
    1385 /*}}}*/
    1386 /*FUNCTION Tria::CreatePVectorDiagnosticMacAyeal {{{1*/
    1387 ElementVector* Tria::CreatePVectorDiagnosticMacAyeal(){
    1388 
    1389         /*Constants*/
    1390         const int    numdof=NDOF2*NUMVERTICES;
    1391 
    1392         /*Intermediaries */
    1393         int            i,j,ig;
    1394         double         driving_stress_baseline,thickness;
    1395         double         Jdet;
    1396         double         xyz_list[NUMVERTICES][3];
    1397         double         slope[2];
    1398         double         basis[3];
    1399         double         pe_g_gaussian[numdof];
    1400         GaussTria*     gauss=NULL;
    1401 
    1402         /*Initialize Element vector*/
    1403         ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters,MacAyealApproximationEnum);
    1404 
    1405         /*Retrieve all inputs and parameters*/
    1406         GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
    1407         Input* thickness_input=inputs->GetInput(ThicknessEnum); _assert_(thickness_input);
    1408         Input* surface_input=inputs->GetInput(SurfaceEnum);     _assert_(surface_input);
    1409         Input* drag_input=inputs->GetInput(FrictionCoefficientEnum);_assert_(drag_input);
    1410 
    1411         /* Start  looping on the number of gaussian points: */
    1412         gauss=new GaussTria(2);
    1413         for(ig=gauss->begin();ig<gauss->end();ig++){
    1414 
    1415                 gauss->GaussPoint(ig);
    1416 
    1417                 GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0],gauss);
    1418                 GetNodalFunctions(basis, gauss);
    1419 
    1420                 thickness_input->GetParameterValue(&thickness,gauss);
    1421                 surface_input->GetParameterDerivativeValue(&slope[0],&xyz_list[0][0],gauss);
    1422                 driving_stress_baseline=matpar->GetRhoIce()*matpar->GetG()*thickness;
    1423 
    1424                 /*Build pe_g_gaussian vector: */
    1425                 for (i=0;i<NUMVERTICES;i++){
    1426                         for (j=0;j<NDOF2;j++){
    1427                                 pe->values[i*NDOF2+j]+=-driving_stress_baseline*slope[j]*Jdet*gauss->weight*basis[i];
    1428                         }
    1429                 }
    1430         }
    1431 
    1432         /*Clean up and return*/
    1433         delete gauss;
    1434         return pe;
    1435 }
    1436 /*}}}*/
    1437 /*FUNCTION Tria::CreatePVectorDiagnosticHutter{{{1*/
    1438 ElementVector* Tria::CreatePVectorDiagnosticHutter(void){
    1439 
    1440         /*Intermediaries */
    1441         int        i,connectivity;
    1442         double     constant_part,ub,vb;
    1443         double     rho_ice,gravity,n,B;
    1444         double     slope2,thickness;
    1445         double     slope[2];
    1446         GaussTria* gauss=NULL;
    1447 
    1448         /*Initialize Element vector*/
    1449         ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters);
    1450 
    1451         /*Retrieve all inputs and parameters*/
    1452         rho_ice=matpar->GetRhoIce();
    1453         gravity=matpar->GetG();
    1454         n=matice->GetN();
    1455         B=matice->GetBbar();
    1456         Input* slopex_input=inputs->GetInput(SurfaceSlopeXEnum); _assert_(slopex_input);
    1457         Input* slopey_input=inputs->GetInput(SurfaceSlopeYEnum); _assert_(slopey_input);
    1458         Input* thickness_input=inputs->GetInput(ThicknessEnum);  _assert_(thickness_input);
    1459 
    1460         /*Spawn 3 sing elements: */
    1461         gauss=new GaussTria();
    1462         for(i=0;i<NUMVERTICES;i++){
    1463 
    1464                 gauss->GaussVertex(i);
    1465 
    1466                 connectivity=nodes[i]->GetConnectivity();
    1467 
    1468                 thickness_input->GetParameterValue(&thickness,gauss);
    1469                 slopex_input->GetParameterValue(&slope[0],gauss);
    1470                 slopey_input->GetParameterValue(&slope[1],gauss);
    1471                 slope2=pow(slope[0],2)+pow(slope[1],2);
    1472 
    1473                 constant_part=-2*pow(rho_ice*gravity,n)*pow(slope2,((n-1)/2));
    1474 
    1475                 ub=-1.58*pow((double)10.0,(double)-10.0)*rho_ice*gravity*thickness*slope[0];
    1476                 vb=-1.58*pow((double)10.0,(double)-10.0)*rho_ice*gravity*thickness*slope[1];
    1477 
    1478                 pe->values[2*i]  =(ub-2.0*pow(rho_ice*gravity,n)*pow(slope2,((n-1)/2.0))*pow(thickness,n)/(pow(B,n)*(n+1))*slope[0])/(double)connectivity;
    1479                 pe->values[2*i+1]=(vb-2.0*pow(rho_ice*gravity,n)*pow(slope2,((n-1)/2.0))*pow(thickness,n)/(pow(B,n)*(n+1))*slope[1])/(double)connectivity;
    1480         }
    1481 
    1482         /*Clean up and return*/
    1483         delete gauss;
    1484         return pe;
    1485 }
    1486 /*}}}*/
    1487784/*FUNCTION Tria::CreatePVectorPrognostic{{{1*/
    1488785ElementVector* Tria::CreatePVectorPrognostic(void){
     
    1496793                        _error_("Element type %s not supported yet",EnumToStringx(GetElementType()));
    1497794        }
    1498 }
    1499 /*}}}*/
    1500 /*FUNCTION Tria::CreatePVectorHydrology {{{1*/
    1501 ElementVector* Tria::CreatePVectorHydrology(void){
    1502 
    1503         /*Constants*/
    1504         const int    numdof=NDOF1*NUMVERTICES;
    1505 
    1506         /*Intermediaries */
    1507         int        i,j,ig;
    1508         double     Jdettria,dt;
    1509         double     basal_melting_g;
    1510         double     old_watercolumn_g;
    1511         double     xyz_list[NUMVERTICES][3];
    1512         double     basis[numdof];
    1513         GaussTria* gauss=NULL;
    1514 
    1515         /*Initialize Element vector*/
    1516         ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters);
    1517 
    1518         /*Retrieve all inputs and parameters*/
    1519         GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
    1520         this->parameters->FindParam(&dt,TimesteppingTimeStepEnum);
    1521         Input* basal_melting_input=inputs->GetInput(BasalforcingsMeltingRateEnum); _assert_(basal_melting_input);
    1522         Input* old_watercolumn_input=inputs->GetInput(WaterColumnOldEnum);         _assert_(old_watercolumn_input);
    1523 
    1524         /*Initialize basal_melting_correction_g to 0, do not forget!:*/
    1525         /* Start  looping on the number of gaussian points: */
    1526         gauss=new GaussTria(2);
    1527         for(ig=gauss->begin();ig<gauss->end();ig++){
    1528 
    1529                 gauss->GaussPoint(ig);
    1530 
    1531                 GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss);
    1532                 GetNodalFunctions(basis, gauss);
    1533 
    1534                 basal_melting_input->GetParameterValue(&basal_melting_g,gauss);
    1535                 old_watercolumn_input->GetParameterValue(&old_watercolumn_g,gauss);
    1536 
    1537                 if(dt)for(i=0;i<numdof;i++) pe->values[i]+=Jdettria*gauss->weight*(old_watercolumn_g+dt*basal_melting_g)*basis[i];
    1538                 else  for(i=0;i<numdof;i++) pe->values[i]+=Jdettria*gauss->weight*basal_melting_g*basis[i];
    1539         }
    1540                
    1541         /*Clean up and return*/
    1542         delete gauss;
    1543         return pe;
    1544795}
    1545796/*}}}*/
     
    19931244
    19941245        /*Just branch to the correct InputUpdateFromSolution generator, according to the type of analysis we are carrying out: */
    1995         if (analysis_type==DiagnosticHorizAnalysisEnum)
    1996          GetSolutionFromInputsDiagnosticHoriz(solution);
    1997         else if (analysis_type==DiagnosticHutterAnalysisEnum)
    1998          GetSolutionFromInputsDiagnosticHutter(solution);
    1999         else if (analysis_type==HydrologyAnalysisEnum)
    2000          GetSolutionFromInputsHydrology(solution);
     1246        switch(analysis_type){
     1247        #ifdef _HAVE_DIAGNOSTIC_
     1248        case DiagnosticHorizAnalysisEnum:
     1249                GetSolutionFromInputsDiagnosticHoriz(solution);
     1250                break;
     1251        case DiagnosticHutterAnalysisEnum:
     1252                GetSolutionFromInputsDiagnosticHutter(solution);
     1253                break;
     1254        #endif
     1255        #ifdef _HAVE_HYDROLOGY_
     1256        case HydrologyAnalysisEnum:
     1257                GetSolutionFromInputsHydrology(solution);
     1258                break;
     1259        #endif
     1260        default:
     1261                _error_("analysis: %s not supported yet",EnumToStringx(analysis_type));
     1262        }
     1263
     1264}
     1265/*}}}*/
     1266/*FUNCTION Tria::GetStrainRate2d(double* epsilon,double* xyz_list, GaussTria* gauss, Input* vx_input, Input* vy_input){{{1*/
     1267void Tria::GetStrainRate2d(double* epsilon,double* xyz_list, GaussTria* gauss, Input* vx_input, Input* vy_input){
     1268        /*Compute the 2d Strain Rate (3 components):
     1269         * epsilon=[exx eyy exy] */
     1270
     1271        int i;
     1272        double epsilonvx[3];
     1273        double epsilonvy[3];
     1274
     1275        /*Check that both inputs have been found*/
     1276        if (!vx_input || !vy_input){
     1277                _error_("Input missing. Here are the input pointers we have for vx: %p, vy: %p\n",vx_input,vy_input);
     1278        }
     1279
     1280        /*Get strain rate assuming that epsilon has been allocated*/
     1281        vx_input->GetVxStrainRate2d(epsilonvx,xyz_list,gauss);
     1282        vy_input->GetVyStrainRate2d(epsilonvy,xyz_list,gauss);
     1283
     1284        /*Sum all contributions*/
     1285        for(i=0;i<3;i++) epsilon[i]=epsilonvx[i]+epsilonvy[i];
     1286}
     1287/*}}}*/
     1288/*FUNCTION Tria::GetVectorFromInputs{{{1*/
     1289void  Tria::GetVectorFromInputs(Vec vector,int input_enum){
     1290
     1291        int doflist1[NUMVERTICES];
     1292
     1293        /*Get out if this is not an element input*/
     1294        if (!IsInput(input_enum)) return;
     1295
     1296        /*Prepare index list*/
     1297        this->GetDofList1(&doflist1[0]);
     1298
     1299        /*Get input (either in element or material)*/
     1300        Input* input=inputs->GetInput(input_enum);
     1301        if(!input) _error_("Input %s not found in element",EnumToStringx(input_enum));
     1302
     1303        /*We found the enum.  Use its values to fill into the vector, using the vertices ids: */
     1304        input->GetVectorFromInputs(vector,&doflist1[0]);
     1305}
     1306/*}}}*/
     1307/*FUNCTION Tria::Id {{{1*/
     1308int    Tria::Id(){
     1309       
     1310        return id;
     1311
     1312}
     1313/*}}}*/
     1314/*FUNCTION Tria::Sid {{{1*/
     1315int    Tria::Sid(){
     1316       
     1317        return sid;
     1318
     1319}
     1320/*}}}*/
     1321/*FUNCTION Tria::InputArtificialNoise{{{1*/
     1322void  Tria::InputArtificialNoise(int enum_type,double min,double max){
     1323
     1324        Input* input=NULL;
     1325
     1326        /*Make a copy of the original input: */
     1327        input=(Input*)this->inputs->GetInput(enum_type);
     1328        if(!input)_error_(" could not find old input with enum: %s",EnumToStringx(enum_type));
     1329
     1330        /*ArtificialNoise: */
     1331        input->ArtificialNoise(min,max);
     1332}
     1333/*}}}*/
     1334/*FUNCTION Tria::InputConvergence{{{1*/
     1335bool Tria::InputConvergence(double* eps, int* enums,int num_enums,int* criterionenums,double* criterionvalues,int num_criterionenums){
     1336
     1337        bool    converged=true;
     1338        int     i;
     1339        Input** new_inputs=NULL;
     1340        Input** old_inputs=NULL;
     1341
     1342        new_inputs=(Input**)xmalloc(num_enums/2*sizeof(Input*)); //half the enums are for the new inputs
     1343        old_inputs=(Input**)xmalloc(num_enums/2*sizeof(Input*)); //half the enums are for the old inputs
     1344
     1345        for(i=0;i<num_enums/2;i++){
     1346                new_inputs[i]=(Input*)this->inputs->GetInput(enums[2*i+0]);
     1347                old_inputs[i]=(Input*)this->inputs->GetInput(enums[2*i+1]);
     1348                if(!new_inputs[i])_error_("%s%s"," could not find input with enum ",EnumToStringx(enums[2*i+0]));
     1349                if(!old_inputs[i])_error_("%s%s"," could not find input with enum ",EnumToStringx(enums[2*i+0]));
     1350        }
     1351
     1352        /*ok, we've got the inputs (new and old), now loop throught the number of criterions and fill the eps array:*/
     1353        for(i=0;i<num_criterionenums;i++){
     1354                IsInputConverged(eps+i,new_inputs,old_inputs,num_enums/2,criterionenums[i]);
     1355                if(eps[i]>criterionvalues[i]) converged=false;
     1356        }
     1357
     1358        /*clean up and return*/
     1359        xfree((void**)&new_inputs);
     1360        xfree((void**)&old_inputs);
     1361        return converged;
     1362}
     1363/*}}}*/
     1364/*FUNCTION Tria::InputDepthAverageAtBase {{{1*/
     1365void  Tria::InputDepthAverageAtBase(int enum_type,int average_enum_type,int object_enum){
     1366
     1367        /*New input*/
     1368        Input* oldinput=NULL;
     1369        Input* newinput=NULL;
     1370
     1371        /*copy input of enum_type*/
     1372        if (object_enum==MeshElementsEnum)
     1373         oldinput=(Input*)this->inputs->GetInput(enum_type);
     1374        else if (object_enum==MaterialsEnum)
     1375         oldinput=(Input*)this->matice->inputs->GetInput(enum_type);
    20011376        else
    2002          _error_("analysis: %s not supported yet",EnumToStringx(analysis_type));
    2003 
     1377         _error_("object %s not supported yet",EnumToStringx(object_enum));
     1378        if(!oldinput)_error_("%s%s"," could not find old input with enum: ",EnumToStringx(enum_type));
     1379        newinput=(Input*)oldinput->copy();
     1380
     1381        /*Assign new name (average)*/
     1382        newinput->ChangeEnum(average_enum_type);
     1383
     1384        /*Add new input to current element*/
     1385        if (object_enum==MeshElementsEnum)
     1386         this->inputs->AddInput((Input*)newinput);
     1387        else if (object_enum==MaterialsEnum)
     1388         this->matice->inputs->AddInput((Input*)newinput);
     1389        else
     1390         _error_("object %s not supported yet",EnumToStringx(object_enum));
     1391}
     1392/*}}}*/
     1393/*FUNCTION Tria::InputDuplicate{{{1*/
     1394void  Tria::InputDuplicate(int original_enum,int new_enum){
     1395
     1396        /*Call inputs method*/
     1397        if (IsInput(original_enum)) inputs->DuplicateInput(original_enum,new_enum);
     1398
     1399}
     1400/*}}}*/
     1401/*FUNCTION Tria::InputScale{{{1*/
     1402void  Tria::InputScale(int enum_type,double scale_factor){
     1403
     1404        Input* input=NULL;
     1405
     1406        /*Make a copy of the original input: */
     1407        input=(Input*)this->inputs->GetInput(enum_type);
     1408        if(!input)_error_(" could not find old input with enum: %s",EnumToStringx(enum_type));
     1409
     1410        /*Scale: */
     1411        input->Scale(scale_factor);
     1412}
     1413/*}}}*/
     1414/*FUNCTION Tria::InputToResult{{{1*/
     1415void  Tria::InputToResult(int enum_type,int step,double time){
     1416
     1417        int    i;
     1418        Input *input = NULL;
     1419
     1420        /*Go through all the input objects, and find the one corresponding to enum_type, if it exists: */
     1421        if (enum_type==MaterialsRheologyBbarEnum) input=this->matice->inputs->GetInput(enum_type);
     1422        else input=this->inputs->GetInput(enum_type);
     1423        if (!input) _error_("Input %s not found in tria->inputs",EnumToStringx(enum_type));
     1424
     1425        /*If we don't find it, no big deal, just don't do the transfer. Otherwise, build a new Result
     1426         * object out of the input, with the additional step and time information: */
     1427        this->results->AddObject((Object*)input->SpawnResult(step,time));
     1428        #ifdef _HAVE_CONTROL_
     1429        if(input->Enum()==ControlInputEnum) this->results->AddObject((Object*)((ControlInput*)input)->SpawnGradient(step,time));
     1430        #endif
     1431}
     1432/*}}}*/
     1433/*FUNCTION Tria::InputUpdateFromConstant(int value, int name);{{{1*/
     1434void  Tria::InputUpdateFromConstant(int constant, int name){
     1435        /*Check that name is an element input*/
     1436        if (!IsInput(name)) return;
     1437
     1438        /*update input*/
     1439        this->inputs->AddInput(new IntInput(name,constant));
     1440}
     1441/*}}}*/
     1442/*FUNCTION Tria::InputUpdateFromConstant(double value, int name);{{{1*/
     1443void  Tria::InputUpdateFromConstant(double constant, int name){
     1444        /*Check that name is an element input*/
     1445        if (!IsInput(name)) return;
     1446
     1447        /*update input*/
     1448        this->inputs->AddInput(new DoubleInput(name,constant));
     1449}
     1450/*}}}*/
     1451/*FUNCTION Tria::InputUpdateFromConstant(bool value, int name);{{{1*/
     1452void  Tria::InputUpdateFromConstant(bool constant, int name){
     1453        /*Check that name is an element input*/
     1454        if (!IsInput(name)) return;
     1455
     1456        /*update input*/
     1457        this->inputs->AddInput(new BoolInput(name,constant));
     1458}
     1459/*}}}*/
     1460/*FUNCTION Tria::InputUpdateFromIoModel{{{1*/
     1461void Tria::InputUpdateFromIoModel(int index, IoModel* iomodel){ //i is the element index
     1462
     1463        /*Intermediaries*/
     1464        int    i,j;
     1465        int    tria_vertex_ids[3];
     1466        double nodeinputs[3];
     1467        double cmmininputs[3];
     1468        double cmmaxinputs[3];
     1469        bool   control_analysis=false;
     1470        int    num_control_type;
     1471        double yts;
     1472        int    num_cm_responses;
     1473   
     1474        /*Get parameters: */
     1475        iomodel->Constant(&control_analysis,InversionIscontrolEnum);
     1476        iomodel->Constant(&num_control_type,InversionNumControlParametersEnum);
     1477        iomodel->Constant(&yts,ConstantsYtsEnum);
     1478        iomodel->Constant(&num_cm_responses,InversionNumCostFunctionsEnum);
     1479
     1480        /*Recover vertices ids needed to initialize inputs*/
     1481        for(i=0;i<3;i++){
     1482                tria_vertex_ids[i]=(int)iomodel->Data(MeshElementsEnum)[3*index+i]; //ids for vertices are in the elements array from Matlab
     1483        }
     1484
     1485        /*Control Inputs*/
     1486        #ifdef _HAVE_CONTROL_
     1487        if (control_analysis && iomodel->Data(InversionControlParametersEnum)){
     1488                for(i=0;i<num_control_type;i++){
     1489                        switch((int)iomodel->Data(InversionControlParametersEnum)[i]){
     1490                                case BalancethicknessThickeningRateEnum:
     1491                                        if (iomodel->Data(BalancethicknessThickeningRateEnum)){
     1492                                                for(j=0;j<3;j++)nodeinputs[j]=iomodel->Data(BalancethicknessThickeningRateEnum)[tria_vertex_ids[j]-1]/yts;
     1493                                                for(j=0;j<3;j++)cmmininputs[j]=iomodel->Data(InversionMinParametersEnum)[(tria_vertex_ids[j]-1)*num_control_type+i]/yts;
     1494                                                for(j=0;j<3;j++)cmmaxinputs[j]=iomodel->Data(InversionMaxParametersEnum)[(tria_vertex_ids[j]-1)*num_control_type+i]/yts;
     1495                                                this->inputs->AddInput(new ControlInput(BalancethicknessThickeningRateEnum,TriaVertexInputEnum,nodeinputs,cmmininputs,cmmaxinputs,i+1));
     1496                                        }
     1497                                        break;
     1498                                case VxEnum:
     1499                                        if (iomodel->Data(VxEnum)){
     1500                                                for(j=0;j<3;j++)nodeinputs[j]=iomodel->Data(VxEnum)[tria_vertex_ids[j]-1]/yts;
     1501                                                for(j=0;j<3;j++)cmmininputs[j]=iomodel->Data(InversionMinParametersEnum)[(tria_vertex_ids[j]-1)*num_control_type+i]/yts;
     1502                                                for(j=0;j<3;j++)cmmaxinputs[j]=iomodel->Data(InversionMaxParametersEnum)[(tria_vertex_ids[j]-1)*num_control_type+i]/yts;
     1503                                                this->inputs->AddInput(new ControlInput(VxEnum,TriaVertexInputEnum,nodeinputs,cmmininputs,cmmaxinputs,i+1));
     1504                                        }
     1505                                        break;
     1506                                case VyEnum:
     1507                                        if (iomodel->Data(VyEnum)){
     1508                                                for(j=0;j<3;j++)nodeinputs[j]=iomodel->Data(VyEnum)[tria_vertex_ids[j]-1]/yts;
     1509                                                for(j=0;j<3;j++)cmmininputs[j]=iomodel->Data(InversionMinParametersEnum)[(tria_vertex_ids[j]-1)*num_control_type+i]/yts;
     1510                                                for(j=0;j<3;j++)cmmaxinputs[j]=iomodel->Data(InversionMaxParametersEnum)[(tria_vertex_ids[j]-1)*num_control_type+i]/yts;
     1511                                                this->inputs->AddInput(new ControlInput(VyEnum,TriaVertexInputEnum,nodeinputs,cmmininputs,cmmaxinputs,i+1));
     1512                                        }
     1513                                        break;
     1514                                case FrictionCoefficientEnum:
     1515                                        if (iomodel->Data(FrictionCoefficientEnum)){
     1516                                                for(j=0;j<3;j++)nodeinputs[j]=iomodel->Data(FrictionCoefficientEnum)[tria_vertex_ids[j]-1];
     1517                                                for(j=0;j<3;j++)cmmininputs[j]=iomodel->Data(InversionMinParametersEnum)[(tria_vertex_ids[j]-1)*num_control_type+i];
     1518                                                for(j=0;j<3;j++)cmmaxinputs[j]=iomodel->Data(InversionMaxParametersEnum)[(tria_vertex_ids[j]-1)*num_control_type+i];
     1519                                                this->inputs->AddInput(new ControlInput(FrictionCoefficientEnum,TriaVertexInputEnum,nodeinputs,cmmininputs,cmmaxinputs,i+1));
     1520                                        }
     1521                                        break;
     1522                                case MaterialsRheologyBbarEnum:
     1523                                        /*Matice will take care of it*/ break;
     1524                                default:
     1525                                        _error_("Control %s not implemented yet",EnumToStringx((int)iomodel->Data(InversionControlParametersEnum)[i]));
     1526                        }
     1527                }
     1528        }
     1529        #endif
     1530
     1531        /*DatasetInputs*/
     1532        if (control_analysis && iomodel->Data(InversionCostFunctionsCoefficientsEnum)){
     1533
     1534                /*Create inputs and add to DataSetInput*/
     1535                DatasetInput* datasetinput=new DatasetInput(InversionCostFunctionsCoefficientsEnum);
     1536                for(i=0;i<num_cm_responses;i++){
     1537                        for(j=0;j<3;j++)nodeinputs[j]=iomodel->Data(InversionCostFunctionsCoefficientsEnum)[(tria_vertex_ids[j]-1)*num_cm_responses+i];
     1538                        datasetinput->inputs->AddObject(new TriaVertexInput(InversionCostFunctionsCoefficientsEnum,nodeinputs));
     1539                }
     1540
     1541                /*Add datasetinput to element inputs*/
     1542                this->inputs->AddInput(datasetinput);
     1543        }
     1544}
     1545/*}}}*/
     1546/*FUNCTION Tria::InputUpdateFromSolution {{{1*/
     1547void  Tria::InputUpdateFromSolution(double* solution){
     1548
     1549        /*retrive parameters: */
     1550        int analysis_type;
     1551        parameters->FindParam(&analysis_type,AnalysisTypeEnum);
     1552
     1553        /*Just branch to the correct InputUpdateFromSolution generator, according to the type of analysis we are carrying out: */
     1554        switch(analysis_type){
     1555                #ifdef _HAVE_DIAGNOSTIC_
     1556                case DiagnosticHorizAnalysisEnum:
     1557                        InputUpdateFromSolutionDiagnosticHoriz( solution);
     1558                        break;
     1559                case DiagnosticHutterAnalysisEnum:
     1560                        InputUpdateFromSolutionDiagnosticHoriz( solution);
     1561                        break;
     1562                #endif
     1563                #ifdef _HAVE_CONTROL_
     1564                case AdjointHorizAnalysisEnum:
     1565                        InputUpdateFromSolutionAdjointHoriz( solution);
     1566                        break;
     1567                case AdjointBalancethicknessAnalysisEnum:
     1568                        InputUpdateFromSolutionAdjointBalancethickness( solution);
     1569                        break;
     1570                #endif
     1571                #ifdef _HAVE_HYDROLOGY_
     1572                case HydrologyAnalysisEnum:
     1573                        InputUpdateFromSolutionHydrology(solution);
     1574                        break ;
     1575                #endif
     1576                #ifdef _HAVE_BALANCED_
     1577                case BalancethicknessAnalysisEnum:
     1578                        InputUpdateFromSolutionOneDof(solution,ThicknessEnum);
     1579                        break;
     1580                #endif
     1581                case BedSlopeXAnalysisEnum:
     1582                        InputUpdateFromSolutionOneDof(solution,BedSlopeXEnum);
     1583                        break;
     1584                case BedSlopeYAnalysisEnum:
     1585                        InputUpdateFromSolutionOneDof(solution,BedSlopeYEnum);
     1586                        break;
     1587                case SurfaceSlopeXAnalysisEnum:
     1588                        InputUpdateFromSolutionOneDof(solution,SurfaceSlopeXEnum);
     1589                        break;
     1590                case SurfaceSlopeYAnalysisEnum:
     1591                        InputUpdateFromSolutionOneDof(solution,SurfaceSlopeYEnum);
     1592                        break;
     1593                case PrognosticAnalysisEnum:
     1594                        InputUpdateFromSolutionPrognostic(solution);
     1595                        break;
     1596                default:
     1597                        _error_("analysis %i (%s) not supported yet",analysis_type,EnumToStringx(analysis_type));
     1598        }
     1599}
     1600/*}}}*/
     1601/*FUNCTION Tria::InputUpdateFromSolutionOneDof{{{1*/
     1602void  Tria::InputUpdateFromSolutionOneDof(double* solution,int enum_type){
     1603
     1604        const int numdof          = NDOF1*NUMVERTICES;
     1605
     1606        int*      doflist=NULL;
     1607        double    values[numdof];
     1608
     1609        /*Get dof list: */
     1610        GetDofList(&doflist,NoneApproximationEnum,GsetEnum);
     1611
     1612        /*Use the dof list to index into the solution vector: */
     1613        for(int i=0;i<numdof;i++){
     1614                values[i]=solution[doflist[i]];
     1615                if(isnan(values[i])) _error_("NaN found in solution vector");
     1616        }
     1617
     1618        /*Add input to the element: */
     1619        this->inputs->AddInput(new TriaVertexInput(enum_type,values));
     1620
     1621        /*Free ressources:*/
     1622        xfree((void**)&doflist);
     1623}
     1624/*}}}*/
     1625/*FUNCTION Tria::InputUpdateFromSolutionPrognostic{{{1*/
     1626void  Tria::InputUpdateFromSolutionPrognostic(double* solution){
     1627
     1628        /*Intermediaries*/
     1629        const int numdof = NDOF1*NUMVERTICES;
     1630
     1631        int       i,dummy,hydroadjustment;
     1632        int*      doflist=NULL;
     1633        double    rho_ice,rho_water;
     1634        double    values[numdof];
     1635        double    bed[numdof];
     1636        double    surface[numdof];
     1637        double    *bed_ptr = NULL;
     1638        double    *thickness_ptr = NULL;
     1639        double    *surface_ptr = NULL;
     1640
     1641        /*Get dof list: */
     1642        GetDofList(&doflist,NoneApproximationEnum,GsetEnum);
     1643
     1644        /*Use the dof list to index into the solution vector: */
     1645        for(i=0;i<numdof;i++){
     1646                values[i]=solution[doflist[i]];
     1647                if(isnan(values[i])) _error_("NaN found in solution vector");
     1648                /*Constrain thickness to be at least 1m*/
     1649                if(values[i]<1) values[i]=1;
     1650        }
     1651
     1652        /*Get previous bed, thickness and surface*/
     1653        Input* bed_input=inputs->GetInput(BedEnum);             _assert_(bed_input);
     1654        Input* thickness_input=inputs->GetInput(ThicknessEnum); _assert_(thickness_input);
     1655        Input* surface_input=inputs->GetInput(SurfaceEnum);     _assert_(surface_input);
     1656        bed_input->GetValuesPtr(&bed_ptr,&dummy);
     1657        thickness_input->GetValuesPtr(&thickness_ptr,&dummy);
     1658        surface_input->GetValuesPtr(&surface_ptr,&dummy);
     1659
     1660        /*Fing PrognosticHydrostaticAdjustment to figure out how to update the geometry:*/
     1661        this->parameters->FindParam(&hydroadjustment,PrognosticHydrostaticAdjustmentEnum);
     1662
     1663        /*recover material parameters: */
     1664        rho_ice=matpar->GetRhoIce();
     1665        rho_water=matpar->GetRhoWater();
     1666
     1667        for(i=0;i<numdof;i++) {
     1668                /*If shelf: hydrostatic equilibrium*/
     1669                if (this->nodes[i]->IsOnSheet()){
     1670                        surface[i]=bed_ptr[i]+values[i]; //surface=oldbed+newthickness
     1671                        bed[i]=bed_ptr[i]; //do nothing
     1672                }
     1673                else{ //this is an ice shelf
     1674
     1675                        if(hydroadjustment==AbsoluteEnum){
     1676                                surface[i]=values[i]*(1-rho_ice/rho_water);
     1677                                bed[i]=values[i]*(-rho_ice/rho_water);
     1678                        }
     1679                        else if(hydroadjustment==IncrementalEnum){
     1680                                surface[i]=surface_ptr[i]+(1.0-rho_ice/rho_water)*(values[i]-thickness_ptr[i]); //surface = oldsurface + (1-di) * dH
     1681                                bed[i]=bed_ptr[i]-rho_ice/rho_water*(values[i]-thickness_ptr[i]); //bed = oldbed + di * dH
     1682                        }
     1683                        else _error_("Hydrostatic adjustment %i (%s) not supported yet",hydroadjustment,EnumToStringx(hydroadjustment));
     1684                }
     1685        }
     1686
     1687        /*Add input to the element: */
     1688        this->inputs->AddInput(new TriaVertexInput(ThicknessEnum,values));
     1689        this->inputs->AddInput(new TriaVertexInput(SurfaceEnum,surface));
     1690        this->inputs->AddInput(new TriaVertexInput(BedEnum,bed));
     1691
     1692        /*Free ressources:*/
     1693        xfree((void**)&doflist);
     1694}
     1695/*}}}*/
     1696/*FUNCTION Tria::InputUpdateFromVector(double* vector, int name, int type);{{{1*/
     1697void  Tria::InputUpdateFromVector(double* vector, int name, int type){
     1698
     1699        /*Check that name is an element input*/
     1700        if (!IsInput(name)) return;
     1701
     1702        switch(type){
     1703
     1704                case VertexEnum:
     1705
     1706                        /*New TriaVertexInput*/
     1707                        double values[3];
     1708
     1709                        /*Get values on the 3 vertices*/
     1710                        for (int i=0;i<3;i++){
     1711                                values[i]=vector[this->nodes[i]->GetVertexDof()];
     1712                        }
     1713
     1714                        /*update input*/
     1715                        if (name==MaterialsRheologyBbarEnum || name==MaterialsRheologyBEnum){
     1716                                matice->inputs->AddInput(new TriaVertexInput(name,values));
     1717                        }
     1718                        else{
     1719                                this->inputs->AddInput(new TriaVertexInput(name,values));
     1720                        }
     1721                        return;
     1722
     1723                default:
     1724                        _error_("type %i (%s) not implemented yet",type,EnumToStringx(type));
     1725        }
     1726}
     1727/*}}}*/
     1728/*FUNCTION Tria::InputUpdateFromVector(int* vector, int name, int type);{{{1*/
     1729void  Tria::InputUpdateFromVector(int* vector, int name, int type){
     1730        _error_(" not supported yet!");
     1731}
     1732/*}}}*/
     1733/*FUNCTION Tria::InputUpdateFromVector(bool* vector, int name, int type);{{{1*/
     1734void  Tria::InputUpdateFromVector(bool* vector, int name, int type){
     1735        _error_(" not supported yet!");
     1736}
     1737/*}}}*/
     1738/*FUNCTION Tria::InputCreate(double scalar,int enum,int code);{{{1*/
     1739void Tria::InputCreate(double scalar,int name,int code){
     1740
     1741        /*Check that name is an element input*/
     1742        if (!IsInput(name)) return;
     1743       
     1744        if ((code==5) || (code==1)){ //boolean
     1745                this->inputs->AddInput(new BoolInput(name,(bool)scalar));
     1746        }
     1747        else if ((code==6) || (code==2)){ //integer
     1748                this->inputs->AddInput(new IntInput(name,(int)scalar));
     1749        }
     1750        else if ((code==7) || (code==3)){ //double
     1751                this->inputs->AddInput(new DoubleInput(name,(int)scalar));
     1752        }
     1753        else _error_("%s%i"," could not recognize nature of vector from code ",code);
     1754
     1755}
     1756/*}}}*/
     1757/*FUNCTION Tria::InputCreate(double* vector,int index,IoModel* iomodel,int M,int N,int vector_type,int vector_enum,int code){{{1*/
     1758void Tria::InputCreate(double* vector, int index,IoModel* iomodel,int M,int N,int vector_type,int vector_enum,int code){//index into elements
     1759
     1760        /*Intermediaries*/
     1761        int    i,j,t;
     1762        int    tria_vertex_ids[3];
     1763        int    row;
     1764        double nodeinputs[3];
     1765        double time;
     1766        TransientInput* transientinput=NULL;
     1767        int    numberofvertices;
     1768        int    numberofelements;
     1769        double yts;
     1770
     1771
     1772        /*Fetch parameters: */
     1773        iomodel->Constant(&numberofvertices,MeshNumberofverticesEnum);
     1774        iomodel->Constant(&numberofelements,MeshNumberofelementsEnum);
     1775        iomodel->Constant(&yts,ConstantsYtsEnum);
     1776
     1777        /*Branch on type of vector: nodal or elementary: */
     1778        if(vector_type==1){ //nodal vector
     1779
     1780                /*Recover vertices ids needed to initialize inputs*/
     1781                for(i=0;i<3;i++){
     1782                        tria_vertex_ids[i]=(int)iomodel->Data(MeshElementsEnum)[3*index+i]; //ids for vertices are in the elements array from Matlab
     1783                }
     1784
     1785                /*Are we in transient or static? */
     1786                if(M==numberofvertices){
     1787
     1788                        /*create input values: */
     1789                        for(i=0;i<3;i++)nodeinputs[i]=(double)vector[tria_vertex_ids[i]-1];
     1790
     1791                        /*process units: */
     1792                        UnitConversion(&nodeinputs[0], 3 ,ExtToIuEnum, vector_enum);
     1793
     1794                        /*create static input: */
     1795                        this->inputs->AddInput(new TriaVertexInput(vector_enum,nodeinputs));
     1796                }
     1797                else if(M==numberofvertices+1){
     1798                        /*create transient input: */
     1799                        for(t=0;t<N;t++){ //N is the number of times
     1800
     1801                                /*create input values: */
     1802                                for(i=0;i<3;i++){
     1803                                        row=tria_vertex_ids[i]-1;
     1804                                        nodeinputs[i]=(double)vector[N*row+t];
     1805                                }
     1806
     1807                                /*process units: */
     1808                                UnitConversion(&nodeinputs[0], 3 ,ExtToIuEnum, vector_enum);
     1809
     1810                                /*time? :*/
     1811                                time=(double)vector[(M-1)*N+t]*yts;
     1812
     1813                                if(t==0) transientinput=new TransientInput(vector_enum);
     1814                                transientinput->AddTimeInput(new TriaVertexInput(vector_enum,nodeinputs),time);
     1815                        }
     1816                        this->inputs->AddInput(transientinput);
     1817                }
     1818                else _error_("nodal vector is either numberofnodes (%i), or numberofnodes+1 long. Field provided is %i long",numberofvertices,M);
     1819        }
     1820        else if(vector_type==2){ //element vector
     1821                /*Are we in transient or static? */
     1822                if(M==numberofelements){
     1823
     1824                        /*static mode: create an input out of the element value: */
     1825
     1826                        if (code==5){ //boolean
     1827                                this->inputs->AddInput(new BoolInput(vector_enum,(bool)vector[index]));
     1828                        }
     1829                        else if (code==6){ //integer
     1830                                this->inputs->AddInput(new IntInput(vector_enum,(int)vector[index]));
     1831                        }
     1832                        else if (code==7){ //double
     1833                                this->inputs->AddInput(new DoubleInput(vector_enum,(double)vector[index]));
     1834                        }
     1835                        else _error_("%s%i"," could not recognize nature of vector from code ",code);
     1836                }
     1837                else {
     1838                        _error_("transient elementary inputs not supported yet!");
     1839                }
     1840        }
     1841        else{
     1842                _error_("Cannot add input for vector type %i (not supported)",vector_type);
     1843        }
     1844
     1845}
     1846/*}}}*/
     1847/*FUNCTION Tria::IsInput{{{1*/
     1848bool Tria::IsInput(int name){
     1849        if (
     1850                                name==ThicknessEnum ||
     1851                                name==SurfaceEnum ||
     1852                                name==BedEnum ||
     1853                                name==SurfaceSlopeXEnum ||
     1854                                name==SurfaceSlopeYEnum ||
     1855                                name==BasalforcingsMeltingRateEnum ||
     1856                                name==WatercolumnEnum ||
     1857                                name==SurfaceforcingsMassBalanceEnum ||
     1858                                name==SurfaceAreaEnum||
     1859                                name==VxEnum ||
     1860                                name==VyEnum ||
     1861                                name==InversionVxObsEnum ||
     1862                                name==InversionVyObsEnum ||
     1863                                name==FrictionCoefficientEnum ||
     1864                                name==GradientEnum ||
     1865                                name==OldGradientEnum
     1866                ){
     1867                return true;
     1868        }
     1869        else return false;
     1870}
     1871/*}}}*/
     1872/*FUNCTION Tria::IsOnBed {{{1*/
     1873bool Tria::IsOnBed(){
     1874       
     1875        bool onbed;
     1876        inputs->GetParameterValue(&onbed,MeshElementonbedEnum);
     1877        return onbed;
     1878}
     1879/*}}}*/
     1880/*FUNCTION Tria::IsOnShelf {{{1*/
     1881bool   Tria::IsOnShelf(){
     1882
     1883        bool shelf;
     1884        inputs->GetParameterValue(&shelf,MaskElementonfloatingiceEnum);
     1885        return shelf;
     1886}
     1887/*}}}*/
     1888/*FUNCTION Tria::IsNodeOnShelf {{{1*/
     1889bool   Tria::IsNodeOnShelf(){
     1890
     1891        int  i;
     1892        bool shelf=false;
     1893
     1894        for(i=0;i<3;i++){
     1895                if (nodes[i]->IsOnShelf()){
     1896                        shelf=true;
     1897                        break;
     1898                }
     1899        }
     1900        return shelf;
     1901}
     1902/*}}}*/
     1903/*FUNCTION Tria::IsNodeOnShelfFromFlags {{{1*/
     1904bool   Tria::IsNodeOnShelfFromFlags(double* flags){
     1905
     1906        int  i;
     1907        bool shelf=false;
     1908
     1909        for(i=0;i<3;i++){
     1910                if (flags[nodes[i]->Sid()]){
     1911                        shelf=true;
     1912                        break;
     1913                }
     1914        }
     1915        return shelf;
     1916}
     1917/*}}}*/
     1918/*FUNCTION Tria::IsOnWater {{{1*/
     1919bool   Tria::IsOnWater(){
     1920
     1921        bool water;
     1922        inputs->GetParameterValue(&water,MaskElementonwaterEnum);
     1923        return water;
     1924}
     1925/*}}}*/
     1926/*FUNCTION Tria::MassFlux {{{1*/
     1927double Tria::MassFlux( double* segment,bool process_units){
     1928
     1929        const int    numdofs=2;
     1930
     1931        int        i;
     1932        double     mass_flux=0;
     1933        double     xyz_list[NUMVERTICES][3];
     1934        double     normal[2];
     1935        double     length,rho_ice;
     1936        double     x1,y1,x2,y2,h1,h2;
     1937        double     vx1,vx2,vy1,vy2;
     1938        GaussTria* gauss_1=NULL;
     1939        GaussTria* gauss_2=NULL;
     1940
     1941        /*Get material parameters :*/
     1942        rho_ice=matpar->GetRhoIce();
     1943
     1944        /*First off, check that this segment belongs to this element: */
     1945        if ((int)*(segment+4)!=this->id)_error_("%s%i%s%i","error message: segment with id ",(int)*(segment+4)," does not belong to element with id:",this->id);
     1946
     1947        /*Recover segment node locations: */
     1948        x1=*(segment+0); y1=*(segment+1); x2=*(segment+2); y2=*(segment+3);
     1949
     1950        /*Get xyz list: */
     1951        GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
     1952
     1953        /*get area coordinates of 0 and 1 locations: */
     1954        gauss_1=new GaussTria();
     1955        gauss_1->GaussFromCoords(x1,y1,&xyz_list[0][0]);
     1956        gauss_2=new GaussTria();
     1957        gauss_2->GaussFromCoords(x2,y2,&xyz_list[0][0]);
     1958
     1959        normal[0]=cos(atan2(x1-x2,y2-y1));
     1960        normal[1]=sin(atan2(x1-x2,y2-y1));
     1961
     1962        length=sqrt(pow(x2-x1,2.0)+pow(y2-y1,2));
     1963
     1964        Input* thickness_input=inputs->GetInput(ThicknessEnum); _assert_(thickness_input);
     1965        Input* vx_input=inputs->GetInput(VxEnum); _assert_(vx_input);
     1966        Input* vy_input=inputs->GetInput(VyEnum); _assert_(vy_input);
     1967
     1968        thickness_input->GetParameterValue(&h1, gauss_1);
     1969        thickness_input->GetParameterValue(&h2, gauss_2);
     1970        vx_input->GetParameterValue(&vx1,gauss_1);
     1971        vx_input->GetParameterValue(&vx2,gauss_2);
     1972        vy_input->GetParameterValue(&vy1,gauss_1);
     1973        vy_input->GetParameterValue(&vy2,gauss_2);
     1974
     1975        mass_flux= rho_ice*length*( 
     1976                                (ONETHIRD*(h1-h2)*(vx1-vx2)+0.5*h2*(vx1-vx2)+0.5*(h1-h2)*vx2+h2*vx2)*normal[0]+
     1977                                (ONETHIRD*(h1-h2)*(vy1-vy2)+0.5*h2*(vy1-vy2)+0.5*(h1-h2)*vy2+h2*vy2)*normal[1]
     1978                                );
     1979
     1980        /*Process units: */
     1981        mass_flux=UnitConversion(mass_flux,IuToExtEnum,MassFluxEnum);
     1982
     1983        /*clean up and return:*/
     1984        delete gauss_1;
     1985        delete gauss_2;
     1986        return mass_flux;
     1987}
     1988/*}}}*/
     1989/*FUNCTION Tria::MaxAbsVx{{{1*/
     1990void  Tria::MaxAbsVx(double* pmaxabsvx, bool process_units){
     1991
     1992        /*Get maximum:*/
     1993        double maxabsvx=this->inputs->MaxAbs(VxEnum);
     1994
     1995        /*process units if requested: */
     1996        if(process_units) maxabsvx=UnitConversion(maxabsvx,IuToExtEnum,VxEnum);
     1997
     1998        /*Assign output pointers:*/
     1999        *pmaxabsvx=maxabsvx;
     2000}
     2001/*}}}*/
     2002/*FUNCTION Tria::MaxAbsVy{{{1*/
     2003void  Tria::MaxAbsVy(double* pmaxabsvy, bool process_units){
     2004
     2005        /*Get maximum:*/
     2006        double maxabsvy=this->inputs->MaxAbs(VyEnum);
     2007
     2008        /*process units if requested: */
     2009        if(process_units) maxabsvy=UnitConversion(maxabsvy,IuToExtEnum,VyEnum);
     2010
     2011        /*Assign output pointers:*/
     2012        *pmaxabsvy=maxabsvy;
     2013}
     2014/*}}}*/
     2015/*FUNCTION Tria::MaxAbsVz{{{1*/
     2016void  Tria::MaxAbsVz(double* pmaxabsvz, bool process_units){
     2017
     2018        /*Get maximum:*/
     2019        double maxabsvz=this->inputs->MaxAbs(VzEnum);
     2020
     2021        /*process units if requested: */
     2022        if(process_units) maxabsvz=UnitConversion(maxabsvz,IuToExtEnum,VyEnum);
     2023
     2024        /*Assign output pointers:*/
     2025        *pmaxabsvz=maxabsvz;
     2026}
     2027/*}}}*/
     2028/*FUNCTION Tria::MaxVel{{{1*/
     2029void  Tria::MaxVel(double* pmaxvel, bool process_units){
     2030
     2031        /*Get maximum:*/
     2032        double maxvel=this->inputs->Max(VelEnum);
     2033
     2034        /*process units if requested: */
     2035        if(process_units) maxvel=UnitConversion(maxvel,IuToExtEnum,VelEnum);
     2036
     2037        /*Assign output pointers:*/
     2038        *pmaxvel=maxvel;
     2039}
     2040/*}}}*/
     2041/*FUNCTION Tria::MaxVx{{{1*/
     2042void  Tria::MaxVx(double* pmaxvx, bool process_units){
     2043
     2044        /*Get maximum:*/
     2045        double maxvx=this->inputs->Max(VxEnum);
     2046
     2047        /*process units if requested: */
     2048        if(process_units) maxvx=UnitConversion(maxvx,IuToExtEnum,VxEnum);
     2049
     2050        /*Assign output pointers:*/
     2051        *pmaxvx=maxvx;
     2052}
     2053/*}}}*/
     2054/*FUNCTION Tria::MaxVy{{{1*/
     2055void  Tria::MaxVy(double* pmaxvy, bool process_units){
     2056
     2057        /*Get maximum:*/
     2058        double maxvy=this->inputs->Max(VyEnum);
     2059
     2060        /*process units if requested: */
     2061        if(process_units) maxvy=UnitConversion(maxvy,IuToExtEnum,VyEnum);
     2062
     2063        /*Assign output pointers:*/
     2064        *pmaxvy=maxvy;
     2065
     2066}
     2067/*}}}*/
     2068/*FUNCTION Tria::MaxVz{{{1*/
     2069void  Tria::MaxVz(double* pmaxvz, bool process_units){
     2070
     2071        /*Get maximum:*/
     2072        double maxvz=this->inputs->Max(VzEnum);
     2073
     2074        /*process units if requested: */
     2075        if(process_units) maxvz=UnitConversion(maxvz,IuToExtEnum,VzEnum);
     2076
     2077        /*Assign output pointers:*/
     2078        *pmaxvz=maxvz;
     2079}
     2080/*}}}*/
     2081/*FUNCTION Tria::MigrateGroundingLine{{{1*/
     2082void  Tria::MigrateGroundingLine(void){
     2083
     2084
     2085        double *values         = NULL;
     2086        double  h[3],s[3],b[3],ba[3];
     2087        double  bed_hydro;
     2088        double  rho_water,rho_ice,density;
     2089        int     isonshelf[3];
     2090        int     i;
     2091        bool    elementonshelf = false;
     2092
     2093
     2094        /*Recover info at the vertices: */
     2095        Input* surface_input =inputs->GetInput(SurfaceEnum); _assert_(surface_input);
     2096        Input* bed_input     =inputs->GetInput(BedEnum);     _assert_(bed_input);
     2097        if((surface_input->Enum()!=TriaVertexInputEnum) | (bed_input->Enum()!=TriaVertexInputEnum))_error_(" not supported yet for bed and surface interpolations not P1!");
     2098
     2099        GetParameterListOnVertices(&h[0],ThicknessEnum);
     2100        GetParameterListOnVertices(&s[0],SurfaceEnum);
     2101        GetParameterListOnVertices(&b[0],BedEnum);
     2102        GetParameterListOnVertices(&ba[0],BathymetryEnum);
     2103        for(i=0;i<3;i++){
     2104                isonshelf[i]=nodes[i]->IsOnShelf();
     2105                if((nodes[i]->Sid()+1)==36)printf("MigrateGroundingLine: El %i Node %i shelf status %i\n",this->Id(),nodes[i]->Sid()+1,isonshelf[i]);
     2106        }
     2107
     2108        /*material parameters: */
     2109        rho_water=matpar->GetRhoWater();
     2110        rho_ice=matpar->GetRhoIce();
     2111        density=rho_ice/rho_water;
     2112
     2113        /*go through vertices, and update inputs, considering them to be TriaVertex type: */
     2114        for(i=0;i<3;i++){
     2115                if (isonshelf[i]){
     2116                        /*This node is on the shelf. See if its bed is going under the bathymetry: */
     2117                        if(b[i]<=ba[i]){ //<= because Neff being 0 when b=ba, drag will be 0 anyway.
     2118                                /*The ice shelf is getting grounded, the thickness is the same, so just update the bed to stick to the bathymetry and elevate the surface accordingly: */
     2119                                b[i]=ba[i];
     2120                                s[i]=b[i]+h[i];
     2121                                if((nodes[i]->Sid()+1)==36)printf("MigrateGroundingLine: El %i Node %i grounding %g %g %g\n",this->Id(),nodes[i]->Sid()+1,b[i],ba[i],s[i]);
     2122                        }
     2123                        else{
     2124                                /*do nothing, we are still floating.*/
     2125                                if((nodes[i]->Sid()+1)==36)printf("MigrateGroundingLine: El %i Node %i still floating %g %g %g\n",this->Id(),nodes[i]->Sid()+1,b[i],ba[i],s[i]);
     2126                        }
     2127                }
     2128                else{
     2129                        /*This node is on the sheet, near the grounding line. See if wants to unground. To
     2130                         * do so, we compute the hydrostatic bed, and if it is > bathymetry, then we unground: */
     2131                        bed_hydro=-density*h[i];
     2132                        if (bed_hydro>ba[i]){
     2133                                /*We are now floating, bed and surface are determined from hydrostatic equilibrium: */
     2134                                s[i]=(1-density)*h[i];
     2135                                b[i]=-density*h[i];
     2136                                printf("%i\n",nodes[i]->Sid()+1);
     2137                                if((nodes[i]->Sid()+1)==36)printf("MigrateGroundingLine: El %i Node %i floating %g %g %g\n",this->Id(),nodes[i]->Sid()+1,b[i],ba[i],s[i]);
     2138                        }
     2139                        else{
     2140                                /*do nothing, we are still grounded.*/
     2141                                if((nodes[i]->Sid()+1)==36)printf("MigrateGroundingLine: El %i Node %i still grounded %g %g %g\n",this->Id(),nodes[i]->Sid()+1,b[i],ba[i],s[i]);
     2142                        }
     2143                }
     2144        }
     2145
     2146        /*Surface and bed are updated. Update inputs:*/
     2147        surface_input->GetValuesPtr(&values,NULL); for(i=0;i<3;i++)values[i]=s[i];
     2148        bed_input->GetValuesPtr(&values,NULL);     for(i=0;i<3;i++)values[i]=b[i];
     2149       
     2150        for(i=0;i<3;i++){
     2151                isonshelf[i]=nodes[i]->IsOnShelf();
     2152                if((nodes[i]->Sid()+1)==36)printf("MigrateGroundingLine: El %i Node %i second shelf status %i\n",this->Id(),nodes[i]->Sid()+1,isonshelf[i]);
     2153        }
     2154}
     2155/*}}}*/
     2156/*FUNCTION Tria::MinVel{{{1*/
     2157void  Tria::MinVel(double* pminvel, bool process_units){
     2158
     2159        /*Get minimum:*/
     2160        double minvel=this->inputs->Min(VelEnum);
     2161
     2162        /*process units if requested: */
     2163        if(process_units) minvel=UnitConversion(minvel,IuToExtEnum,VelEnum);
     2164
     2165        /*Assign output pointers:*/
     2166        *pminvel=minvel;
     2167}
     2168/*}}}*/
     2169/*FUNCTION Tria::MinVx{{{1*/
     2170void  Tria::MinVx(double* pminvx, bool process_units){
     2171
     2172        /*Get minimum:*/
     2173        double minvx=this->inputs->Min(VxEnum);
     2174
     2175        /*process units if requested: */
     2176        if(process_units) minvx=UnitConversion(minvx,IuToExtEnum,VxEnum);
     2177
     2178        /*Assign output pointers:*/
     2179        *pminvx=minvx;
     2180}
     2181/*}}}*/
     2182/*FUNCTION Tria::MinVy{{{1*/
     2183void  Tria::MinVy(double* pminvy, bool process_units){
     2184
     2185        /*Get minimum:*/
     2186        double minvy=this->inputs->Min(VyEnum);
     2187
     2188        /*process units if requested: */
     2189        if(process_units) minvy=UnitConversion(minvy,IuToExtEnum,VyEnum);
     2190
     2191        /*Assign output pointers:*/
     2192        *pminvy=minvy;
     2193}
     2194/*}}}*/
     2195/*FUNCTION Tria::MinVz{{{1*/
     2196void  Tria::MinVz(double* pminvz, bool process_units){
     2197
     2198        /*Get minimum:*/
     2199        double minvz=this->inputs->Min(VzEnum);
     2200
     2201        /*process units if requested: */
     2202        if(process_units) minvz=UnitConversion(minvz,IuToExtEnum,VzEnum);
     2203
     2204        /*Assign output pointers:*/
     2205        *pminvz=minvz;
     2206}
     2207/*}}}*/
     2208/*FUNCTION Tria::MyRank {{{1*/
     2209int    Tria::MyRank(void){
     2210        extern int my_rank;
     2211        return my_rank;
     2212}
     2213/*}}}*/
     2214/*FUNCTION Tria::NodalValue {{{1*/
     2215int    Tria::NodalValue(double* pvalue, int index, int natureofdataenum,bool process_units){
     2216
     2217        int i;
     2218        int found=0;
     2219        double value;
     2220        Input* data=NULL;
     2221        GaussTria *gauss                            = NULL;
     2222
     2223        /*First, serarch the input: */
     2224        data=inputs->GetInput(natureofdataenum);
     2225
     2226        /*figure out if we have the vertex id: */
     2227        found=0;
     2228        for(i=0;i<NUMVERTICES;i++){
     2229                if(index==nodes[i]->GetVertexId()){
     2230                        /*Do we have natureofdataenum in our inputs? :*/
     2231                        if(data){
     2232                                /*ok, we are good. retrieve value of input at vertex :*/
     2233                                gauss=new GaussTria(); gauss->GaussVertex(i);
     2234                                data->GetParameterValue(&value,gauss);
     2235                                found=1;
     2236                                break;
     2237                        }
     2238                }
     2239        }
     2240
     2241        if(found)*pvalue=value;
     2242        return found;
     2243}
     2244/*}}}*/
     2245/*FUNCTION Tria::PatchFill{{{1*/
     2246void  Tria::PatchFill(int* prow, Patch* patch){
     2247
     2248        int i,row;
     2249        int vertices_ids[3];
     2250
     2251        /*recover pointer: */
     2252        row=*prow;
     2253               
     2254        for(i=0;i<3;i++) vertices_ids[i]=nodes[i]->GetVertexId(); //vertices id start at column 3 of the patch.
     2255
     2256        for(i=0;i<this->results->Size();i++){
     2257                ElementResult* elementresult=(ElementResult*)this->results->GetObjectByOffset(i);
     2258
     2259                /*For this result,fill the information in the Patch object (element id + vertices ids), and then hand
     2260                 *it to the result object, to fill the rest: */
     2261                patch->fillelementinfo(row,this->sid+1,vertices_ids,3);
     2262                elementresult->PatchFill(row,patch);
     2263
     2264                /*increment rower: */
     2265                row++;
     2266        }
     2267
     2268        /*Assign output pointers:*/
     2269        *prow=row;
     2270}
     2271/*}}}*/
     2272/*FUNCTION Tria::PatchSize{{{1*/
     2273void  Tria::PatchSize(int* pnumrows, int* pnumvertices,int* pnumnodes){
     2274
     2275        int     i;
     2276        int     numrows     = 0;
     2277        int     numnodes    = 0;
     2278        int     temp_numnodes    = 0;
     2279
     2280        /*Go through all the results objects, and update the counters: */
     2281        for (i=0;i<this->results->Size();i++){
     2282                ElementResult* elementresult=(ElementResult*)this->results->GetObjectByOffset(i);
     2283                /*first, we have one more result: */
     2284                numrows++;
     2285                /*now, how many vertices and how many nodal values for this result? :*/
     2286                temp_numnodes=elementresult->NumberOfNodalValues(); //ask result object.
     2287                if(temp_numnodes>numnodes)numnodes=temp_numnodes;
     2288        }
     2289
     2290        /*Assign output pointers:*/
     2291        *pnumrows=numrows;
     2292        *pnumvertices=NUMVERTICES;
     2293        *pnumnodes=numnodes;
     2294}
     2295/*}}}*/
     2296/*FUNCTION Tria::PotentialSheetUngrounding{{{1*/
     2297void  Tria::PotentialSheetUngrounding(Vec potential_sheet_ungrounding){
     2298
     2299
     2300        double *values         = NULL;
     2301        double  h[3],s[3],b[3],ba[3];
     2302        double  bed_hydro;
     2303        double  rho_water,rho_ice,density;
     2304        int     i;
     2305        bool    elementonshelf = false;
     2306
     2307        /*Recover info at the vertices: */
     2308        Input* surface_input =inputs->GetInput(SurfaceEnum); _assert_(surface_input);
     2309        Input* bed_input     =inputs->GetInput(BedEnum);     _assert_(bed_input);
     2310        if((surface_input->Enum()!=TriaVertexInputEnum) | (bed_input->Enum()!=TriaVertexInputEnum))_error_(" not supported yet for bed and surface interpolations not P1!");
     2311
     2312        GetParameterListOnVertices(&h[0],ThicknessEnum);
     2313        GetParameterListOnVertices(&s[0],SurfaceEnum);
     2314        GetParameterListOnVertices(&b[0],BedEnum);
     2315        GetParameterListOnVertices(&ba[0],BathymetryEnum);
     2316
     2317        /*material parameters: */
     2318        rho_water=matpar->GetRhoWater();
     2319        rho_ice=matpar->GetRhoIce();
     2320        density=rho_ice/rho_water;
     2321
     2322        /*go through vertices, and figure out which ones are on the ice sheet, and want to unground: */
     2323        for(i=0;i<3;i++){
     2324                if (!nodes[i]->IsOnShelf()){
     2325                       
     2326                        /*This node is on the sheet, near the grounding line. See if wants to unground. To
     2327                         * do so, we compute the hydrostatic bed, and if it is > bathymetry, then we unground: */
     2328                        bed_hydro=-density*h[i];
     2329                        if (bed_hydro>ba[i]){
     2330                                /*ok, this node wants to unground. flag it: */
     2331                                VecSetValue(potential_sheet_ungrounding,nodes[i]->Sid(),1,INSERT_VALUES);
     2332                        }
     2333                }
     2334        }
     2335}
     2336/*}}}*/
     2337/*FUNCTION Tria::ProcessResultsUnits{{{1*/
     2338void  Tria::ProcessResultsUnits(void){
     2339
     2340        int i;
     2341
     2342        for(i=0;i<this->results->Size();i++){
     2343                ElementResult* elementresult=(ElementResult*)this->results->GetObjectByOffset(i);
     2344                elementresult->ProcessUnits(this->parameters);
     2345        }
     2346}
     2347/*}}}*/
     2348/*FUNCTION Tria::RheologyBbarx{{{1*/
     2349double Tria::RheologyBbarx(void){
     2350
     2351        return this->matice->GetBbar();
     2352
     2353}
     2354/*}}}*/
     2355/*FUNCTION Tria::RequestedOutput{{{1*/
     2356void Tria::RequestedOutput(int output_enum,int step,double time){
     2357
     2358        if(IsInput(output_enum)){
     2359                /*just transfer this input to results, and we are done: */
     2360                InputToResult(output_enum,step,time);
     2361        }
     2362        else{
     2363                /*this input does not exist, compute it, and then transfer to results: */
     2364                switch(output_enum){
     2365                        default:
     2366                                /*do nothing, no need to derail the computation because one of the outputs requested cannot be found: */
     2367                                break;
     2368                }
     2369        }
     2370
     2371}
     2372/*}}}*/
     2373/*FUNCTION Tria::SetClone {{{1*/
     2374void  Tria::SetClone(int* minranks){
     2375
     2376        _error_("not implemented yet");
     2377}
     2378/*}}}1*/
     2379/*FUNCTION Tria::SetCurrentConfiguration {{{1*/
     2380void  Tria::SetCurrentConfiguration(Elements* elementsin, Loads* loadsin, DataSet* nodesin, Materials* materialsin, Parameters* parametersin){
     2381       
     2382        /*go into parameters and get the analysis_counter: */
     2383        int analysis_counter;
     2384        parametersin->FindParam(&analysis_counter,AnalysisCounterEnum);
     2385
     2386        /*Get Element type*/
     2387        this->element_type=this->element_type_list[analysis_counter];
     2388
     2389        /*Pick up nodes*/
     2390        if(this->hnodes[analysis_counter]) this->nodes=(Node**)this->hnodes[analysis_counter]->deliverp();
     2391        else this->nodes=NULL;
     2392
     2393}
     2394/*}}}*/
     2395/*FUNCTION Tria::ShelfSync{{{1*/
     2396void  Tria::ShelfSync(void){
     2397
     2398
     2399        double *values         = NULL;
     2400        double  h[3],s[3],b[3],ba[3];
     2401        double  bed_hydro;
     2402        double  rho_water,rho_ice,density;
     2403        int     i;
     2404        bool    elementonshelf = false;
     2405
     2406        /*melting rate at the grounding line: */
     2407        double  yts;
     2408        int     swap;
     2409        double  gl_melting_rate;
     2410
     2411        /*recover parameters: */
     2412        parameters->FindParam(&yts,ConstantsYtsEnum);
     2413        parameters->FindParam(&gl_melting_rate,GroundinglineMeltingRateEnum);
     2414
     2415        /*Recover info at the vertices: */
     2416        Input* surface_input =inputs->GetInput(SurfaceEnum); _assert_(surface_input);
     2417        Input* bed_input     =inputs->GetInput(BedEnum);     _assert_(bed_input);
     2418        if((surface_input->Enum()!=TriaVertexInputEnum) | (bed_input->Enum()!=TriaVertexInputEnum))_error_(" not supported yet for bed and surface interpolations not P1!");
     2419
     2420        GetParameterListOnVertices(&h[0],ThicknessEnum);
     2421        GetParameterListOnVertices(&s[0],SurfaceEnum);
     2422        GetParameterListOnVertices(&b[0],BedEnum);
     2423        GetParameterListOnVertices(&ba[0],BathymetryEnum);
     2424
     2425        /*material parameters: */
     2426        rho_water=matpar->GetRhoWater();
     2427        rho_ice=matpar->GetRhoIce();
     2428        density=rho_ice/rho_water;
     2429
     2430        /*go through vertices, and update inputs, considering them to be TriaVertex type: */
     2431        for(i=0;i<3;i++){
     2432                if(b[i]==ba[i]){
     2433                               
     2434                        nodes[i]->inputs->AddInput(new BoolInput(MaskVertexonfloatingiceEnum,false));
     2435                        nodes[i]->inputs->AddInput(new BoolInput(MaskVertexongroundediceEnum,true));
     2436                }
     2437                else{
     2438                        nodes[i]->inputs->AddInput(new BoolInput(MaskVertexonfloatingiceEnum,true));
     2439                        nodes[i]->inputs->AddInput(new BoolInput(MaskVertexongroundediceEnum,false));
     2440
     2441                }
     2442        }
     2443
     2444        /*Now, update  shelf status of element. An element can only be on shelf if all its nodes are on shelf: */
     2445        swap=0;
     2446        elementonshelf=false;
     2447        for(i=0;i<3;i++){
     2448                if(nodes[i]->IsOnShelf()){
     2449                        elementonshelf=true;
     2450                        break;
     2451                }
     2452        }
     2453        if(!this->IsOnShelf() && elementonshelf==true)swap=1;
     2454    this->inputs->AddInput(new BoolInput(MaskElementonfloatingiceEnum,elementonshelf));
     2455       
     2456    /*If this element just  became ungrounded, set its basal melting rate at 50 m/yr:*/
     2457        if(swap){
     2458                Input* basal_melting_rate_input     =inputs->GetInput(BasalforcingsMeltingRateEnum);     _assert_(basal_melting_rate_input);
     2459                basal_melting_rate_input->GetValuesPtr(&values,NULL); for(i=0;i<3;i++)values[i]=gl_melting_rate/yts;
     2460        }
     2461
     2462
     2463}
     2464/*}}}*/
     2465/*FUNCTION Tria::SoftMigration{{{1*/
     2466void  Tria::SoftMigration(double* sheet_ungrounding){
     2467
     2468
     2469        double *values         = NULL;
     2470        double  h[3],s[3],b[3],ba[3];
     2471        double  bed_hydro;
     2472        double  rho_water,rho_ice,density;
     2473        int     i;
     2474        bool    elementonshelf = false;
     2475
     2476        /*Recover info at the vertices: */
     2477        Input* surface_input =inputs->GetInput(SurfaceEnum); _assert_(surface_input);
     2478        Input* bed_input     =inputs->GetInput(BedEnum);     _assert_(bed_input);
     2479        if((surface_input->Enum()!=TriaVertexInputEnum) | (bed_input->Enum()!=TriaVertexInputEnum))_error_(" not supported yet for bed and surface interpolations not P1!");
     2480
     2481        GetParameterListOnVertices(&h[0],ThicknessEnum);
     2482        GetParameterListOnVertices(&s[0],SurfaceEnum);
     2483        GetParameterListOnVertices(&b[0],BedEnum);
     2484        GetParameterListOnVertices(&ba[0],BathymetryEnum);
     2485
     2486        /*material parameters: */
     2487        rho_water=matpar->GetRhoWater();
     2488        rho_ice=matpar->GetRhoIce();
     2489        density=rho_ice/rho_water;
     2490       
     2491        /*go through vertices, and update inputs, considering them to be TriaVertex type: */
     2492        for(i=0;i<3;i++){
     2493                if (nodes[i]->IsOnShelf()){
     2494                        /*This node is on the shelf. See if its bed is going under the bathymetry: */
     2495                        if(b[i]<=ba[i]){ //<= because Neff being 0 when b=ba, drag will be 0 anyway.
     2496                                /*The ice shelf is getting grounded, the thickness is the same, so just update the bed to stick to the bathymetry and elevate the surface accordingly: */
     2497                                b[i]=ba[i];
     2498                                s[i]=b[i]+h[i];
     2499                        }
     2500                        else{
     2501                                /*do nothing, we are still floating.*/
     2502                        }
     2503                }
     2504                else{
     2505                        /*This node is on the sheet, near the grounding line. See if wants to unground. To
     2506                         * do so, we compute the hydrostatic bed, and if it is > bathymetry, then we unground: */
     2507                        bed_hydro=-density*h[i];
     2508                        if (bed_hydro>ba[i]){
     2509
     2510                                /*Now, are we connected to the grounding line, if so, go forward, otherwise, bail out: */
     2511                                if(sheet_ungrounding[nodes[i]->Sid()]){
     2512                                        /*We are now floating, bed and surface are determined from hydrostatic equilibrium: */
     2513                                        s[i]=(1-density)*h[i];
     2514                                        b[i]=-density*h[i];
     2515                                }
     2516                        }
     2517                        else{
     2518                                /*do nothing, we are still grounded.*/
     2519                        }
     2520                }
     2521        }
     2522
     2523        /*Surface and bed are updated. Update inputs:*/   
     2524        surface_input->GetValuesPtr(&values,NULL); for(i=0;i<3;i++)values[i]=s[i];
     2525        bed_input->GetValuesPtr(&values,NULL);     for(i=0;i<3;i++)values[i]=b[i];
     2526
     2527        }
     2528/*}}}*/
     2529/*FUNCTION Tria::SurfaceArea {{{1*/
     2530double Tria::SurfaceArea(void){
     2531
     2532        int    i;
     2533        double S;
     2534        double normal[3];
     2535        double v13[3],v23[3];
     2536        double xyz_list[NUMVERTICES][3];
     2537
     2538        /*If on water, return 0: */
     2539        if(IsOnWater())return 0;
     2540
     2541        GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
     2542
     2543        for (i=0;i<3;i++){
     2544                v13[i]=xyz_list[0][i]-xyz_list[2][i];
     2545                v23[i]=xyz_list[1][i]-xyz_list[2][i];
     2546        }
     2547
     2548        normal[0]=v13[1]*v23[2]-v13[2]*v23[1];
     2549        normal[1]=v13[2]*v23[0]-v13[0]*v23[2];
     2550        normal[2]=v13[0]*v23[1]-v13[1]*v23[0];
     2551
     2552        S = 0.5 * sqrt(pow(normal[0],(double)2)+pow(normal[1],(double)2)+pow(normal[2],(double)2));
     2553
     2554        /*Return: */
     2555        return S;
     2556}
     2557/*}}}*/
     2558/*FUNCTION Tria::SurfaceNormal{{{1*/
     2559void Tria::SurfaceNormal(double* surface_normal, double xyz_list[3][3]){
     2560
     2561        int i;
     2562        double v13[3],v23[3];
     2563        double normal[3];
     2564        double normal_norm;
     2565
     2566        for (i=0;i<3;i++){
     2567                v13[i]=xyz_list[0][i]-xyz_list[2][i];
     2568                v23[i]=xyz_list[1][i]-xyz_list[2][i];
     2569        }
     2570
     2571        normal[0]=v13[1]*v23[2]-v13[2]*v23[1];
     2572        normal[1]=v13[2]*v23[0]-v13[0]*v23[2];
     2573        normal[2]=v13[0]*v23[1]-v13[1]*v23[0];
     2574
     2575        normal_norm=sqrt( pow(normal[0],(double)2)+pow(normal[1],(double)2)+pow(normal[2],(double)2) );
     2576
     2577        *(surface_normal)=normal[0]/normal_norm;
     2578        *(surface_normal+1)=normal[1]/normal_norm;
     2579        *(surface_normal+2)=normal[2]/normal_norm;
     2580}
     2581/*}}}*/
     2582/*FUNCTION Tria::TimeAdapt{{{1*/
     2583double  Tria::TimeAdapt(void){
     2584
     2585        /*intermediary: */
     2586        int    i;
     2587        double C,dt;
     2588        double dx,dy;
     2589        double maxx,minx;
     2590        double maxy,miny;
     2591        double maxabsvx,maxabsvy;
     2592        double xyz_list[NUMVERTICES][3];
     2593
     2594        /*get CFL coefficient:*/
     2595        this->parameters->FindParam(&C,TimesteppingCflCoefficientEnum);
     2596
     2597        /*Get for Vx and Vy, the max of abs value: */
     2598        this->MaxAbsVx(&maxabsvx,false);
     2599        this->MaxAbsVy(&maxabsvy,false);
     2600
     2601        /* Get node coordinates and dof list: */
     2602        GetVerticesCoordinates(&xyz_list[0][0], this->nodes, NUMVERTICES);
     2603
     2604        minx=xyz_list[0][0];
     2605        maxx=xyz_list[0][0];
     2606        miny=xyz_list[0][1];
     2607        maxy=xyz_list[0][1];
     2608
     2609        for(i=1;i<NUMVERTICES;i++){
     2610                if (xyz_list[i][0]<minx)minx=xyz_list[i][0];
     2611                if (xyz_list[i][0]>maxx)maxx=xyz_list[i][0];
     2612                if (xyz_list[i][1]<miny)miny=xyz_list[i][1];
     2613                if (xyz_list[i][1]>maxy)maxy=xyz_list[i][1];
     2614        }
     2615        dx=maxx-minx;
     2616        dy=maxy-miny;
     2617
     2618        /*CFL criterion: */
     2619        dt=C/(maxabsvy/dx+maxabsvy/dy);
     2620
     2621        return dt;
     2622}
     2623/*}}}*/
     2624/*FUNCTION Tria::Update(int index, IoModel* iomodel,int analysis_counter,int analysis_type){{{1*/
     2625void Tria::Update(int index, IoModel* iomodel,int analysis_counter,int analysis_type){ //i is the element index
     2626
     2627        /*Intermediaries*/
     2628        int    i,j;
     2629        int    tria_node_ids[3];
     2630        int    tria_vertex_ids[3];
     2631        int    tria_type;
     2632        double nodeinputs[3];
     2633        double yts;
     2634        int    progstabilization,balancestabilization;
     2635        bool   dakota_analysis;
     2636
     2637        /*Checks if debuging*/
     2638        /*{{{2*/
     2639        _assert_(iomodel->Data(MeshElementsEnum));
     2640        /*}}}*/
     2641
     2642        /*Fetch parameters: */
     2643        iomodel->Constant(&yts,ConstantsYtsEnum);
     2644        iomodel->Constant(&progstabilization,PrognosticStabilizationEnum);
     2645        iomodel->Constant(&balancestabilization,BalancethicknessStabilizationEnum);
     2646        iomodel->Constant(&dakota_analysis,QmuIsdakotaEnum);
     2647
     2648        /*Recover element type*/
     2649        if ((analysis_type==PrognosticAnalysisEnum && progstabilization==3) || (analysis_type==BalancethicknessAnalysisEnum && balancestabilization==3)){
     2650                /*P1 Discontinuous Galerkin*/
     2651                tria_type=P1DGEnum;
     2652        }
     2653        else{
     2654                /*P1 Continuous Galerkin*/
     2655                tria_type=P1Enum;
     2656        }
     2657        this->SetElementType(tria_type,analysis_counter);
     2658
     2659        /*Recover vertices ids needed to initialize inputs*/
     2660        for(i=0;i<3;i++){
     2661                tria_vertex_ids[i]=(int)iomodel->Data(MeshElementsEnum)[3*index+i]; //ids for vertices are in the elements array from Matlab
     2662        }
     2663
     2664        /*Recover nodes ids needed to initialize the node hook.*/
     2665        if (tria_type==P1DGEnum){
     2666                /*Discontinuous Galerkin*/
     2667                tria_node_ids[0]=iomodel->nodecounter+3*index+1;
     2668                tria_node_ids[1]=iomodel->nodecounter+3*index+2;
     2669                tria_node_ids[2]=iomodel->nodecounter+3*index+3;
     2670        }
     2671        else{
     2672                /*Continuous Galerkin*/
     2673                for(i=0;i<3;i++){
     2674                        tria_node_ids[i]=iomodel->nodecounter+(int)*(iomodel->Data(MeshElementsEnum)+3*index+i); //ids for vertices are in the elements array from Matlab
     2675                }
     2676        }
     2677
     2678        /*hooks: */
     2679        this->SetHookNodes(tria_node_ids,analysis_counter); this->nodes=NULL; //set hook to nodes, for this analysis type
     2680
     2681        /*Fill with IoModel*/
     2682        this->InputUpdateFromIoModel(index,iomodel);
     2683
     2684        /*Defaults if not provided in iomodel*/
     2685        switch(analysis_type){
     2686
     2687                case DiagnosticHorizAnalysisEnum:
     2688
     2689                        /*default vx,vy and vz: either observation or 0 */
     2690                        if(!iomodel->Data(VxEnum)){
     2691                                if (iomodel->Data(InversionVxObsEnum)) for(i=0;i<3;i++)nodeinputs[i]=iomodel->Data(InversionVxObsEnum)[tria_vertex_ids[i]-1]/yts;
     2692                                else                 for(i=0;i<3;i++)nodeinputs[i]=0;
     2693                                this->inputs->AddInput(new TriaVertexInput(VxEnum,nodeinputs));
     2694                                this->inputs->AddInput(new TriaVertexInput(VxPicardEnum,nodeinputs));
     2695                                if(dakota_analysis) this->inputs->AddInput(new TriaVertexInput(QmuVxEnum,nodeinputs));
     2696                        }
     2697                        if(!iomodel->Data(VyEnum)){
     2698                                if (iomodel->Data(InversionVyObsEnum)) for(i=0;i<3;i++)nodeinputs[i]=iomodel->Data(InversionVyObsEnum)[tria_vertex_ids[i]-1]/yts;
     2699                                else                 for(i=0;i<3;i++)nodeinputs[i]=0;
     2700                                this->inputs->AddInput(new TriaVertexInput(VyEnum,nodeinputs));
     2701                                this->inputs->AddInput(new TriaVertexInput(VyPicardEnum,nodeinputs));
     2702                                if(dakota_analysis) this->inputs->AddInput(new TriaVertexInput(QmuVyEnum,nodeinputs));
     2703                        }
     2704                        if(!iomodel->Data(VzEnum)){
     2705                                if (iomodel->Data(InversionVzObsEnum)) for(i=0;i<3;i++)nodeinputs[i]=iomodel->Data(InversionVzObsEnum)[tria_vertex_ids[i]-1]/yts;
     2706                                else                 for(i=0;i<3;i++)nodeinputs[i]=0;
     2707                                this->inputs->AddInput(new TriaVertexInput(VzEnum,nodeinputs));
     2708                                this->inputs->AddInput(new TriaVertexInput(VzPicardEnum,nodeinputs));
     2709                                if(dakota_analysis) this->inputs->AddInput(new TriaVertexInput(QmuVzEnum,nodeinputs));
     2710                        }
     2711                        if(!iomodel->Data(PressureEnum)){
     2712                                for(i=0;i<3;i++)nodeinputs[i]=0;
     2713                                if(dakota_analysis){
     2714                                        this->inputs->AddInput(new TriaVertexInput(PressureEnum,nodeinputs));
     2715                                        this->inputs->AddInput(new TriaVertexInput(QmuPressureEnum,nodeinputs));
     2716                                }
     2717                        }
     2718                        break;
     2719
     2720                default:
     2721                        /*No update for other solution types*/
     2722                        break;
     2723
     2724        }
     2725
     2726        //this->parameters: we still can't point to it, it may not even exist. Configure will handle this.
     2727        this->parameters=NULL;
     2728}
     2729/*}}}*/
     2730/*FUNCTION Tria::UpdateShelfStatus{{{1*/
     2731int  Tria::UpdateShelfStatus(Vec new_shelf_nodes){
     2732
     2733        int     i;
     2734
     2735        double  h[3];
     2736        double  s[3];
     2737        double  b[3];
     2738        double  ba[3];
     2739        Input  *surface_input  = NULL;
     2740        Input  *bed_input      = NULL;
     2741        double  rho_water;
     2742        double  rho_ice;
     2743        double  density;
     2744        bool    elementonshelf = false;
     2745        int     flipped=0;
     2746        int     shelfstatus[3];
     2747
     2748
     2749        /*Recover info at the vertices: */
     2750        surface_input   =inputs->GetInput(SurfaceEnum);   _assert_(surface_input);
     2751        bed_input   =inputs->GetInput(BedEnum);   _assert_(bed_input);
     2752        if((surface_input->Enum()!=TriaVertexInputEnum) | (bed_input->Enum()!=TriaVertexInputEnum))_error_(" not supported yet for bed and surface interpolations not P1!");
     2753
     2754        GetParameterListOnVertices(&h[0],ThicknessEnum);
     2755        GetParameterListOnVertices(&s[0],SurfaceEnum);
     2756        GetParameterListOnVertices(&b[0],BedEnum);
     2757        GetParameterListOnVertices(&ba[0],BathymetryEnum);
     2758
     2759        /*material parameters: */
     2760        rho_water=matpar->GetRhoWater();
     2761        rho_ice=matpar->GetRhoIce();
     2762        density=rho_ice/rho_water;
     2763
     2764        /*Initialize current status of nodes: */
     2765        for(i=0;i<3;i++){
     2766                shelfstatus[i]=nodes[i]->IsOnShelf();
     2767                if((nodes[i]->Sid()+1)==36) printf("UpdateShelfStatus: El %i Node %i shelf status %i\n",this->Id(),nodes[i]->Sid()+1,shelfstatus[i]);
     2768        }
     2769       
     2770        /*go through vertices, and figure out if they are grounded or not, then update their status: */
     2771        flipped=0;
     2772        for(i=0;i<3;i++){
     2773                if(b[i]<=ba[i]){ //the = will lead to oscillations.
     2774                        nodes[i]->inputs->AddInput(new BoolInput(MaskVertexonfloatingiceEnum,false));
     2775                        nodes[i]->inputs->AddInput(new BoolInput(MaskVertexongroundediceEnum,true));
     2776                        if(shelfstatus[i]){
     2777                                flipped++;
     2778                                if((nodes[i]->Sid()+1)==36)printf("UpdateShelfStatus: El %i Node %i grounding %g %g %g\n",this->Id(),nodes[i]->Sid()+1,b[i],ba[i],s[i]);
     2779                        }
     2780                        VecSetValue(new_shelf_nodes,nodes[i]->Sid(),0,INSERT_VALUES);
     2781                }
     2782                else{
     2783                        nodes[i]->inputs->AddInput(new BoolInput(MaskVertexonfloatingiceEnum,true));
     2784                        nodes[i]->inputs->AddInput(new BoolInput(MaskVertexongroundediceEnum,false));
     2785                        if(!shelfstatus[i]){
     2786                                flipped++;
     2787                                if((nodes[i]->Sid()+1)==36)printf("UpdateShelfStatus: El %i Node %i floating %g %g %g\n",this->Id(),nodes[i]->Sid()+1,b[i],ba[i],s[i]);
     2788                        }
     2789                        VecSetValue(new_shelf_nodes,nodes[i]->Sid(),1,INSERT_VALUES);
     2790                }
     2791        }
     2792
     2793        /*Now, update  shelf status of element. An element can only be on shelf if all its nodes are on shelf: */
     2794        elementonshelf=false;
     2795        for(i=0;i<3;i++){
     2796                if(nodes[i]->IsOnShelf()){
     2797                        elementonshelf=true;
     2798                        break;
     2799                }
     2800        }
     2801    this->inputs->AddInput(new BoolInput(MaskElementonfloatingiceEnum,elementonshelf));
     2802
     2803         return flipped;
     2804}
     2805/*}}}*/
     2806/*FUNCTION Tria::UpdateShelfFlags{{{1*/
     2807void Tria::UpdateShelfFlags(double* new_shelf_nodes){
     2808
     2809        /*go through vertices, and update the status of MaskVertexonfloatingiceEnum and MaskVertexongroundediceEnum flags: */
     2810        bool flag;
     2811        int  i;
     2812        double  h[3];
     2813        double  s[3];
     2814        double  b[3];
     2815        double  ba[3];
     2816
     2817        GetParameterListOnVertices(&h[0],ThicknessEnum);
     2818        GetParameterListOnVertices(&s[0],SurfaceEnum);
     2819        GetParameterListOnVertices(&b[0],BedEnum);
     2820        GetParameterListOnVertices(&ba[0],BathymetryEnum);
     2821
     2822        for(i=0;i<3;i++){
     2823                flag=(bool)new_shelf_nodes[nodes[i]->Sid()];
     2824                nodes[i]->inputs->AddInput(new BoolInput(MaskVertexonfloatingiceEnum,flag));
     2825                nodes[i]->inputs->AddInput(new BoolInput(MaskVertexongroundediceEnum,!flag));
     2826        }
     2827}
     2828/*}}}*/
     2829/*FUNCTION Tria::UpdatePotentialSheetUngrounding{{{1*/
     2830int Tria::UpdatePotentialSheetUngrounding(double* potential_sheet_ungrounding,Vec vec_nodes_on_iceshelf,double* nodes_on_iceshelf){
     2831
     2832        /*intermediary: */
     2833        int i;
     2834        int nflipped=0;
     2835
     2836        /*Ok, go through our 3 nodes, and whoever is on the potential_sheet_ungrounding, ends up in nodes_on_iceshelf: */
     2837        for(i=0;i<3;i++){
     2838                if (potential_sheet_ungrounding[nodes[i]->Sid()]){
     2839                        VecSetValue(vec_nodes_on_iceshelf,nodes[i]->Sid(),1,INSERT_VALUES);
     2840               
     2841                        /*Figure out if we flipped: */
     2842                        if (potential_sheet_ungrounding[nodes[i]->Sid()] != nodes_on_iceshelf[nodes[i]->Sid()])nflipped++;
     2843                }
     2844        }
     2845        return nflipped;
     2846}
     2847/*}}}*/
     2848
     2849#ifdef _HAVE_DIAGNOSTIC_
     2850/*FUNCTION Tria::CreateKMatrixDiagnosticMacAyeal {{{1*/
     2851ElementMatrix* Tria::CreateKMatrixDiagnosticMacAyeal(void){
     2852
     2853        /*compute all stiffness matrices for this element*/
     2854        ElementMatrix* Ke1=CreateKMatrixDiagnosticMacAyealViscous();
     2855        ElementMatrix* Ke2=CreateKMatrixDiagnosticMacAyealFriction();
     2856        ElementMatrix* Ke =new ElementMatrix(Ke1,Ke2);
     2857       
     2858        /*clean-up and return*/
     2859        delete Ke1;
     2860        delete Ke2;
     2861        return Ke;
     2862}
     2863/*}}}*/
     2864/*FUNCTION Tria::CreateKMatrixDiagnosticMacAyealViscous{{{1*/
     2865ElementMatrix* Tria::CreateKMatrixDiagnosticMacAyealViscous(void){
     2866
     2867        /*Constants*/
     2868        const int  numdof=NDOF2*NUMVERTICES;
     2869
     2870        /*Intermediaries*/
     2871        int        i,j,ig;
     2872        double     xyz_list[NUMVERTICES][3];
     2873        double     viscosity,newviscosity,oldviscosity;
     2874        double     viscosity_overshoot,thickness,Jdet;
     2875        double     epsilon[3],oldepsilon[3];    /* epsilon=[exx,eyy,exy];    */
     2876        double     B[3][numdof];
     2877        double     Bprime[3][numdof];
     2878        double     D[3][3]   = {0.0};
     2879        double     D_scalar;
     2880        GaussTria *gauss = NULL;
     2881
     2882        /*Initialize Element matrix*/
     2883        ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,MacAyealApproximationEnum);
     2884
     2885        /*Retrieve all inputs and parameters*/
     2886        GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
     2887        Input* thickness_input=inputs->GetInput(ThicknessEnum); _assert_(thickness_input);
     2888        Input* vx_input=inputs->GetInput(VxEnum);               _assert_(vx_input);
     2889        Input* vy_input=inputs->GetInput(VyEnum);               _assert_(vy_input);
     2890        Input* vxold_input=inputs->GetInput(VxPicardEnum);      _assert_(vxold_input);
     2891        Input* vyold_input=inputs->GetInput(VyPicardEnum);      _assert_(vyold_input);
     2892        this->parameters->FindParam(&viscosity_overshoot,DiagnosticViscosityOvershootEnum);
     2893
     2894        /* Start  looping on the number of gaussian points: */
     2895        gauss=new GaussTria(2);
     2896        for (ig=gauss->begin();ig<gauss->end();ig++){
     2897
     2898                gauss->GaussPoint(ig);
     2899
     2900                GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0],gauss);
     2901                GetBMacAyeal(&B[0][0], &xyz_list[0][0], gauss);
     2902                GetBprimeMacAyeal(&Bprime[0][0], &xyz_list[0][0], gauss);
     2903
     2904                this->GetStrainRate2d(&epsilon[0],&xyz_list[0][0],gauss,vx_input,vy_input);
     2905                this->GetStrainRate2d(&oldepsilon[0],&xyz_list[0][0],gauss,vxold_input,vyold_input);
     2906                matice->GetViscosity2d(&viscosity, &epsilon[0]);
     2907                matice->GetViscosity2d(&oldviscosity, &oldepsilon[0]);
     2908                thickness_input->GetParameterValue(&thickness, gauss);
     2909
     2910                newviscosity=viscosity+viscosity_overshoot*(viscosity-oldviscosity);
     2911                D_scalar=2*newviscosity*thickness*gauss->weight*Jdet;
     2912                for (i=0;i<3;i++) D[i][i]=D_scalar;
     2913
     2914                TripleMultiply(&B[0][0],3,numdof,1,
     2915                                        &D[0][0],3,3,0,
     2916                                        &Bprime[0][0],3,numdof,0,
     2917                                        &Ke->values[0],1);
     2918        }
     2919
     2920        /*Clean up and return*/
     2921        delete gauss;
     2922        return Ke;
     2923}
     2924/*}}}*/
     2925/*FUNCTION Tria::CreateKMatrixDiagnosticMacAyealFriction {{{1*/
     2926ElementMatrix* Tria::CreateKMatrixDiagnosticMacAyealFriction(void){
     2927
     2928        /*Constants*/
     2929        const int  numdof=NDOF2*NUMVERTICES;
     2930
     2931        /*Intermediaries*/
     2932        int        i,j,ig;
     2933        int        analysis_type;
     2934        double     MAXSLOPE  = .06; // 6 %
     2935        double     MOUNTAINKEXPONENT = 10;
     2936        double     slope_magnitude,alpha2;
     2937        double     Jdet;
     2938        double     L[2][numdof];
     2939        double     DL[2][2]  = {{ 0,0 },{0,0}};
     2940        double     DL_scalar;
     2941        double     slope[2]  = {0.0,0.0};
     2942        double     xyz_list[NUMVERTICES][3];
     2943        Friction  *friction = NULL;
     2944        GaussTria *gauss    = NULL;
     2945
     2946        /*Initialize Element matrix and return if necessary*/
     2947        if(IsOnShelf()) return NULL;
     2948        ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,MacAyealApproximationEnum);
     2949
     2950        /*Retrieve all inputs and parameters*/
     2951        GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
     2952        Input* surface_input=inputs->GetInput(SurfaceEnum); _assert_(surface_input);
     2953        Input* vx_input=inputs->GetInput(VxEnum);           _assert_(vx_input);
     2954        Input* vy_input=inputs->GetInput(VyEnum);           _assert_(vy_input);
     2955        Input* vz_input=inputs->GetInput(VzEnum);           _assert_(vz_input);
     2956        parameters->FindParam(&analysis_type,AnalysisTypeEnum);
     2957
     2958        /*build friction object, used later on: */
     2959        friction=new Friction("2d",inputs,matpar,analysis_type);
     2960
     2961        /* Start  looping on the number of gaussian points: */
     2962        gauss=new GaussTria(2);
     2963        for (ig=gauss->begin();ig<gauss->end();ig++){
     2964
     2965                gauss->GaussPoint(ig);
     2966
     2967                // If we have a slope > 6% for this element,  it means  we are on a mountain. In this particular case,
     2968                //velocity should be = 0. To achieve this result, we set alpha2_list to a very high value: */
     2969                surface_input->GetParameterDerivativeValue(&slope[0],&xyz_list[0][0],gauss);
     2970                slope_magnitude=sqrt(pow(slope[0],2)+pow(slope[1],2));
     2971                if(slope_magnitude>MAXSLOPE) alpha2=pow((double)10,MOUNTAINKEXPONENT);
     2972                else friction->GetAlpha2(&alpha2, gauss,VxEnum,VyEnum,VzEnum);
     2973
     2974                GetL(&L[0][0], &xyz_list[0][0], gauss,NDOF2);
     2975                GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0],gauss);
     2976                DL_scalar=alpha2*gauss->weight*Jdet;
     2977                for (i=0;i<2;i++) DL[i][i]=DL_scalar;
     2978               
     2979                TripleMultiply( &L[0][0],2,numdof,1,
     2980                                        &DL[0][0],2,2,0,
     2981                                        &L[0][0],2,numdof,0,
     2982                                        &Ke->values[0],1);
     2983        }
     2984
     2985        /*Clean up and return*/
     2986        delete gauss;
     2987        delete friction;
     2988        return Ke;
     2989}
     2990/*}}}*/
     2991/*FUNCTION Tria::CreateKMatrixDiagnosticHutter{{{1*/
     2992ElementMatrix* Tria::CreateKMatrixDiagnosticHutter(void){
     2993
     2994        /*Intermediaries*/
     2995        const int numdof=NUMVERTICES*NDOF2;
     2996        int    i,connectivity;
     2997
     2998        /*Initialize Element matrix*/
     2999        ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,NoneApproximationEnum);
     3000
     3001        /*Create Element matrix*/
     3002        for(i=0;i<NUMVERTICES;i++){
     3003                connectivity=nodes[i]->GetConnectivity();
     3004                Ke->values[(2*i)*numdof  +(2*i)  ]=1/(double)connectivity;
     3005                Ke->values[(2*i+1)*numdof+(2*i+1)]=1/(double)connectivity;
     3006        }
     3007
     3008        /*Clean up and return*/
     3009        return Ke;
     3010}
     3011/*}}}*/
     3012/*FUNCTION Tria::CreatePVectorDiagnosticMacAyeal {{{1*/
     3013ElementVector* Tria::CreatePVectorDiagnosticMacAyeal(){
     3014
     3015        /*Constants*/
     3016        const int    numdof=NDOF2*NUMVERTICES;
     3017
     3018        /*Intermediaries */
     3019        int            i,j,ig;
     3020        double         driving_stress_baseline,thickness;
     3021        double         Jdet;
     3022        double         xyz_list[NUMVERTICES][3];
     3023        double         slope[2];
     3024        double         basis[3];
     3025        double         pe_g_gaussian[numdof];
     3026        GaussTria*     gauss=NULL;
     3027
     3028        /*Initialize Element vector*/
     3029        ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters,MacAyealApproximationEnum);
     3030
     3031        /*Retrieve all inputs and parameters*/
     3032        GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
     3033        Input* thickness_input=inputs->GetInput(ThicknessEnum); _assert_(thickness_input);
     3034        Input* surface_input=inputs->GetInput(SurfaceEnum);     _assert_(surface_input);
     3035        Input* drag_input=inputs->GetInput(FrictionCoefficientEnum);_assert_(drag_input);
     3036
     3037        /* Start  looping on the number of gaussian points: */
     3038        gauss=new GaussTria(2);
     3039        for(ig=gauss->begin();ig<gauss->end();ig++){
     3040
     3041                gauss->GaussPoint(ig);
     3042
     3043                GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0],gauss);
     3044                GetNodalFunctions(basis, gauss);
     3045
     3046                thickness_input->GetParameterValue(&thickness,gauss);
     3047                surface_input->GetParameterDerivativeValue(&slope[0],&xyz_list[0][0],gauss);
     3048                driving_stress_baseline=matpar->GetRhoIce()*matpar->GetG()*thickness;
     3049
     3050                /*Build pe_g_gaussian vector: */
     3051                for (i=0;i<NUMVERTICES;i++){
     3052                        for (j=0;j<NDOF2;j++){
     3053                                pe->values[i*NDOF2+j]+=-driving_stress_baseline*slope[j]*Jdet*gauss->weight*basis[i];
     3054                        }
     3055                }
     3056        }
     3057
     3058        /*Clean up and return*/
     3059        delete gauss;
     3060        return pe;
     3061}
     3062/*}}}*/
     3063/*FUNCTION Tria::CreatePVectorDiagnosticHutter{{{1*/
     3064ElementVector* Tria::CreatePVectorDiagnosticHutter(void){
     3065
     3066        /*Intermediaries */
     3067        int        i,connectivity;
     3068        double     constant_part,ub,vb;
     3069        double     rho_ice,gravity,n,B;
     3070        double     slope2,thickness;
     3071        double     slope[2];
     3072        GaussTria* gauss=NULL;
     3073
     3074        /*Initialize Element vector*/
     3075        ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters);
     3076
     3077        /*Retrieve all inputs and parameters*/
     3078        rho_ice=matpar->GetRhoIce();
     3079        gravity=matpar->GetG();
     3080        n=matice->GetN();
     3081        B=matice->GetBbar();
     3082        Input* slopex_input=inputs->GetInput(SurfaceSlopeXEnum); _assert_(slopex_input);
     3083        Input* slopey_input=inputs->GetInput(SurfaceSlopeYEnum); _assert_(slopey_input);
     3084        Input* thickness_input=inputs->GetInput(ThicknessEnum);  _assert_(thickness_input);
     3085
     3086        /*Spawn 3 sing elements: */
     3087        gauss=new GaussTria();
     3088        for(i=0;i<NUMVERTICES;i++){
     3089
     3090                gauss->GaussVertex(i);
     3091
     3092                connectivity=nodes[i]->GetConnectivity();
     3093
     3094                thickness_input->GetParameterValue(&thickness,gauss);
     3095                slopex_input->GetParameterValue(&slope[0],gauss);
     3096                slopey_input->GetParameterValue(&slope[1],gauss);
     3097                slope2=pow(slope[0],2)+pow(slope[1],2);
     3098
     3099                constant_part=-2*pow(rho_ice*gravity,n)*pow(slope2,((n-1)/2));
     3100
     3101                ub=-1.58*pow((double)10.0,(double)-10.0)*rho_ice*gravity*thickness*slope[0];
     3102                vb=-1.58*pow((double)10.0,(double)-10.0)*rho_ice*gravity*thickness*slope[1];
     3103
     3104                pe->values[2*i]  =(ub-2.0*pow(rho_ice*gravity,n)*pow(slope2,((n-1)/2.0))*pow(thickness,n)/(pow(B,n)*(n+1))*slope[0])/(double)connectivity;
     3105                pe->values[2*i+1]=(vb-2.0*pow(rho_ice*gravity,n)*pow(slope2,((n-1)/2.0))*pow(thickness,n)/(pow(B,n)*(n+1))*slope[1])/(double)connectivity;
     3106        }
     3107
     3108        /*Clean up and return*/
     3109        delete gauss;
     3110        return pe;
    20043111}
    20053112/*}}}*/
     
    20823189}
    20833190/*}}}*/
    2084 /*FUNCTION Tria::GetSolutionFromInputsHydrology{{{1*/
    2085 void  Tria::GetSolutionFromInputsHydrology(Vec solution){
    2086 
    2087         const int    numdof=NDOF1*NUMVERTICES;
    2088 
    2089         int i,dummy;
    2090         int*         doflist=NULL;
    2091         double       watercolumn;
    2092         double       values[numdof];
    2093         GaussTria*   gauss=NULL;
    2094 
     3191/*FUNCTION Tria::InputUpdateFromSolutionDiagnosticHoriz {{{1*/
     3192void  Tria::InputUpdateFromSolutionDiagnosticHoriz(double* solution){
     3193       
     3194        const int numdof=NDOF2*NUMVERTICES;
     3195
     3196        int       i;
     3197        int       dummy;
     3198        int*      doflist=NULL;
     3199        double    rho_ice,g;
     3200        double    values[numdof];
     3201        double    vx[NUMVERTICES];
     3202        double    vy[NUMVERTICES];
     3203        double    vz[NUMVERTICES];
     3204        double    vel[NUMVERTICES];
     3205        double    pressure[NUMVERTICES];
     3206        double    thickness[NUMVERTICES];
     3207       
    20953208        /*Get dof list: */
    20963209        GetDofList(&doflist,NoneApproximationEnum,GsetEnum);
    20973210
    2098         /*Get inputs*/
    2099         Input* watercolumn_input=inputs->GetInput(WatercolumnEnum); _assert_(watercolumn_input);
    2100 
    2101         /*Ok, we have watercolumn values, fill in watercolumn array: */
    2102         /*P1 element only for now*/
    2103         gauss=new GaussTria();
     3211        /*Use the dof list to index into the solution vector: */
     3212        for(i=0;i<numdof;i++) values[i]=solution[doflist[i]];
     3213
     3214        /*Ok, we have vx and vy in values, fill in vx and vy arrays: */
    21043215        for(i=0;i<NUMVERTICES;i++){
    2105 
    2106                 gauss->GaussVertex(i);
    2107 
    2108                 /*Recover watercolumn*/
    2109                 watercolumn_input->GetParameterValue(&watercolumn,gauss);
    2110                 values[i]=watercolumn;
    2111         }
    2112 
    2113         VecSetValues(solution,numdof,doflist,(const double*)values,INSERT_VALUES);
     3216                vx[i]=values[i*NDOF2+0];
     3217                vy[i]=values[i*NDOF2+1];
     3218
     3219                /*Check solution*/
     3220                if(isnan(vx[i])) _error_("NaN found in solution vector");
     3221                if(isnan(vy[i])) _error_("NaN found in solution vector");
     3222        }
     3223
     3224        /*Get Vz and compute vel*/
     3225        GetParameterListOnVertices(&vz[0],VzEnum,0);
     3226        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);
     3227
     3228        /*For pressure: we have not computed pressure in this analysis, for this element. We are in 2D,
     3229         *so the pressure is just the pressure at the bedrock: */
     3230        rho_ice=matpar->GetRhoIce();
     3231        g=matpar->GetG();
     3232        GetParameterListOnVertices(&thickness[0],ThicknessEnum);
     3233        for(i=0;i<NUMVERTICES;i++) pressure[i]=rho_ice*g*thickness[i];
     3234
     3235        /*Now, we have to move the previous Vx and Vy inputs  to old
     3236         * status, otherwise, we'll wipe them off: */
     3237        this->inputs->ChangeEnum(VxEnum,VxPicardEnum);
     3238        this->inputs->ChangeEnum(VyEnum,VyPicardEnum);
     3239        this->inputs->ChangeEnum(PressureEnum,PressurePicardEnum);
     3240
     3241        /*Add vx and vy as inputs to the tria element: */
     3242        this->inputs->AddInput(new TriaVertexInput(VxEnum,vx));
     3243        this->inputs->AddInput(new TriaVertexInput(VyEnum,vy));
     3244        this->inputs->AddInput(new TriaVertexInput(VelEnum,vel));
     3245        this->inputs->AddInput(new TriaVertexInput(PressureEnum,pressure));
    21143246
    21153247        /*Free ressources:*/
    2116         delete gauss;
    21173248        xfree((void**)&doflist);
    2118 }
    2119 /*}}}*/
    2120 /*FUNCTION Tria::GetStrainRate2d(double* epsilon,double* xyz_list, GaussTria* gauss, Input* vx_input, Input* vy_input){{{1*/
    2121 void Tria::GetStrainRate2d(double* epsilon,double* xyz_list, GaussTria* gauss, Input* vx_input, Input* vy_input){
    2122         /*Compute the 2d Strain Rate (3 components):
    2123          * epsilon=[exx eyy exy] */
    2124 
    2125         int i;
    2126         double epsilonvx[3];
    2127         double epsilonvy[3];
    2128 
    2129         /*Check that both inputs have been found*/
    2130         if (!vx_input || !vy_input){
    2131                 _error_("Input missing. Here are the input pointers we have for vx: %p, vy: %p\n",vx_input,vy_input);
    2132         }
    2133 
    2134         /*Get strain rate assuming that epsilon has been allocated*/
    2135         vx_input->GetVxStrainRate2d(epsilonvx,xyz_list,gauss);
    2136         vy_input->GetVyStrainRate2d(epsilonvy,xyz_list,gauss);
    2137 
    2138         /*Sum all contributions*/
    2139         for(i=0;i<3;i++) epsilon[i]=epsilonvx[i]+epsilonvy[i];
    2140 }
    2141 /*}}}*/
    2142 /*FUNCTION Tria::GetVectorFromInputs{{{1*/
    2143 void  Tria::GetVectorFromInputs(Vec vector,int input_enum){
    2144 
    2145         int doflist1[NUMVERTICES];
    2146 
    2147         /*Get out if this is not an element input*/
    2148         if (!IsInput(input_enum)) return;
    2149 
    2150         /*Prepare index list*/
    2151         this->GetDofList1(&doflist1[0]);
    2152 
    2153         /*Get input (either in element or material)*/
    2154         Input* input=inputs->GetInput(input_enum);
    2155         if(!input) _error_("Input %s not found in element",EnumToStringx(input_enum));
    2156 
    2157         /*We found the enum.  Use its values to fill into the vector, using the vertices ids: */
    2158         input->GetVectorFromInputs(vector,&doflist1[0]);
    2159 }
    2160 /*}}}*/
    2161 /*FUNCTION Tria::Id {{{1*/
    2162 int    Tria::Id(){
     3249
     3250}
     3251/*}}}*/
     3252/*FUNCTION Tria::InputUpdateFromSolutionDiagnosticHutter {{{1*/
     3253void  Tria::InputUpdateFromSolutionDiagnosticHutter(double* solution){
    21633254       
    2164         return id;
    2165 
    2166 }
    2167 /*}}}*/
    2168 /*FUNCTION Tria::Sid {{{1*/
    2169 int    Tria::Sid(){
     3255        const int numdof=NDOF2*NUMVERTICES;
    21703256       
    2171         return sid;
    2172 
    2173 }
    2174 /*}}}*/
    2175 /*FUNCTION Tria::InputArtificialNoise{{{1*/
    2176 void  Tria::InputArtificialNoise(int enum_type,double min,double max){
    2177 
    2178         Input* input=NULL;
    2179 
    2180         /*Make a copy of the original input: */
    2181         input=(Input*)this->inputs->GetInput(enum_type);
    2182         if(!input)_error_(" could not find old input with enum: %s",EnumToStringx(enum_type));
    2183 
    2184         /*ArtificialNoise: */
    2185         input->ArtificialNoise(min,max);
    2186 }
    2187 /*}}}*/
     3257        int       i;
     3258        int       dummy;
     3259        int*      doflist=NULL;
     3260        double    rho_ice,g;
     3261        double    values[numdof];
     3262        double    vx[NUMVERTICES];
     3263        double    vy[NUMVERTICES];
     3264        double    vz[NUMVERTICES];
     3265        double    vel[NUMVERTICES];
     3266        double    pressure[NUMVERTICES];
     3267        double    thickness[NUMVERTICES];
     3268        double*   vz_ptr=NULL;
     3269        Input*    vz_input=NULL;
     3270       
     3271        /*Get dof list: */
     3272        GetDofList(&doflist,NoneApproximationEnum,GsetEnum);
     3273
     3274        /*Use the dof list to index into the solution vector: */
     3275        for(i=0;i<numdof;i++) values[i]=solution[doflist[i]];
     3276
     3277        /*Ok, we have vx and vy in values, fill in vx and vy arrays: */
     3278        for(i=0;i<NUMVERTICES;i++){
     3279                vx[i]=values[i*NDOF2+0];
     3280                vy[i]=values[i*NDOF2+1];
     3281
     3282                /*Check solution*/
     3283                if(isnan(vx[i])) _error_("NaN found in solution vector");
     3284                if(isnan(vy[i])) _error_("NaN found in solution vector");
     3285        }
     3286
     3287        /*Get Vz*/
     3288        vz_input=inputs->GetInput(VzEnum);
     3289        if (vz_input){
     3290                if (vz_input->Enum()!=TriaVertexInputEnum){
     3291                        _error_("Cannot compute Vel as Vz is of type %s",EnumToStringx(vz_input->Enum()));
     3292                }
     3293                vz_input->GetValuesPtr(&vz_ptr,&dummy);
     3294                for(i=0;i<NUMVERTICES;i++) vz[i]=vz_ptr[i];
     3295        }
     3296        else{
     3297                for(i=0;i<NUMVERTICES;i++) vz[i]=0.0;
     3298        }
     3299
     3300        /*Now Compute vel*/
     3301        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);
     3302
     3303        /*For pressure: we have not computed pressure in this analysis, for this element. We are in 2D,
     3304         *so the pressure is just the pressure at the bedrock: */
     3305        rho_ice=matpar->GetRhoIce();
     3306        g=matpar->GetG();
     3307        GetParameterListOnVertices(&thickness[0],ThicknessEnum);
     3308        for(i=0;i<NUMVERTICES;i++) pressure[i]=rho_ice*g*thickness[i];
     3309
     3310        /*Now, we have to move the previous Vx and Vy inputs  to old
     3311         * status, otherwise, we'll wipe them off: */
     3312        this->inputs->ChangeEnum(VxEnum,VxPicardEnum);
     3313        this->inputs->ChangeEnum(VyEnum,VyPicardEnum);
     3314        this->inputs->ChangeEnum(PressureEnum,PressurePicardEnum);
     3315
     3316        /*Add vx and vy as inputs to the tria element: */
     3317        this->inputs->AddInput(new TriaVertexInput(VxEnum,vx));
     3318        this->inputs->AddInput(new TriaVertexInput(VyEnum,vy));
     3319        this->inputs->AddInput(new TriaVertexInput(VelEnum,vel));
     3320        this->inputs->AddInput(new TriaVertexInput(PressureEnum,pressure));
     3321
     3322        /*Free ressources:*/
     3323        xfree((void**)&doflist);
     3324}
     3325/*}}}*/
     3326
     3327#endif
    21883328
    21893329#ifdef _HAVE_CONTROL_
     
    35864726}
    35874727/*}}}*/
    3588 #endif
    3589 
    3590 /*FUNCTION Tria::InputConvergence{{{1*/
    3591 bool Tria::InputConvergence(double* eps, int* enums,int num_enums,int* criterionenums,double* criterionvalues,int num_criterionenums){
    3592 
    3593         bool    converged=true;
    3594         int     i;
    3595         Input** new_inputs=NULL;
    3596         Input** old_inputs=NULL;
    3597 
    3598         new_inputs=(Input**)xmalloc(num_enums/2*sizeof(Input*)); //half the enums are for the new inputs
    3599         old_inputs=(Input**)xmalloc(num_enums/2*sizeof(Input*)); //half the enums are for the old inputs
    3600 
    3601         for(i=0;i<num_enums/2;i++){
    3602                 new_inputs[i]=(Input*)this->inputs->GetInput(enums[2*i+0]);
    3603                 old_inputs[i]=(Input*)this->inputs->GetInput(enums[2*i+1]);
    3604                 if(!new_inputs[i])_error_("%s%s"," could not find input with enum ",EnumToStringx(enums[2*i+0]));
    3605                 if(!old_inputs[i])_error_("%s%s"," could not find input with enum ",EnumToStringx(enums[2*i+0]));
    3606         }
    3607 
    3608         /*ok, we've got the inputs (new and old), now loop throught the number of criterions and fill the eps array:*/
    3609         for(i=0;i<num_criterionenums;i++){
    3610                 IsInputConverged(eps+i,new_inputs,old_inputs,num_enums/2,criterionenums[i]);
    3611                 if(eps[i]>criterionvalues[i]) converged=false;
    3612         }
    3613 
    3614         /*clean up and return*/
    3615         xfree((void**)&new_inputs);
    3616         xfree((void**)&old_inputs);
    3617         return converged;
    3618 }
    3619 /*}}}*/
    3620 /*FUNCTION Tria::InputDepthAverageAtBase {{{1*/
    3621 void  Tria::InputDepthAverageAtBase(int enum_type,int average_enum_type,int object_enum){
    3622 
    3623         /*New input*/
    3624         Input* oldinput=NULL;
    3625         Input* newinput=NULL;
    3626 
    3627         /*copy input of enum_type*/
    3628         if (object_enum==MeshElementsEnum)
    3629          oldinput=(Input*)this->inputs->GetInput(enum_type);
    3630         else if (object_enum==MaterialsEnum)
    3631          oldinput=(Input*)this->matice->inputs->GetInput(enum_type);
    3632         else
    3633          _error_("object %s not supported yet",EnumToStringx(object_enum));
    3634         if(!oldinput)_error_("%s%s"," could not find old input with enum: ",EnumToStringx(enum_type));
    3635         newinput=(Input*)oldinput->copy();
    3636 
    3637         /*Assign new name (average)*/
    3638         newinput->ChangeEnum(average_enum_type);
    3639 
    3640         /*Add new input to current element*/
    3641         if (object_enum==MeshElementsEnum)
    3642          this->inputs->AddInput((Input*)newinput);
    3643         else if (object_enum==MaterialsEnum)
    3644          this->matice->inputs->AddInput((Input*)newinput);
    3645         else
    3646          _error_("object %s not supported yet",EnumToStringx(object_enum));
    3647 }
    3648 /*}}}*/
    3649 /*FUNCTION Tria::InputDuplicate{{{1*/
    3650 void  Tria::InputDuplicate(int original_enum,int new_enum){
    3651 
    3652         /*Call inputs method*/
    3653         if (IsInput(original_enum)) inputs->DuplicateInput(original_enum,new_enum);
    3654 
    3655 }
    3656 /*}}}*/
    3657 /*FUNCTION Tria::InputScale{{{1*/
    3658 void  Tria::InputScale(int enum_type,double scale_factor){
    3659 
    3660         Input* input=NULL;
    3661 
    3662         /*Make a copy of the original input: */
    3663         input=(Input*)this->inputs->GetInput(enum_type);
    3664         if(!input)_error_(" could not find old input with enum: %s",EnumToStringx(enum_type));
    3665 
    3666         /*Scale: */
    3667         input->Scale(scale_factor);
    3668 }
    3669 /*}}}*/
    3670 /*FUNCTION Tria::InputToResult{{{1*/
    3671 void  Tria::InputToResult(int enum_type,int step,double time){
    3672 
    3673         int    i;
    3674         Input *input = NULL;
    3675 
    3676         /*Go through all the input objects, and find the one corresponding to enum_type, if it exists: */
    3677         if (enum_type==MaterialsRheologyBbarEnum) input=this->matice->inputs->GetInput(enum_type);
    3678         else input=this->inputs->GetInput(enum_type);
    3679         if (!input) _error_("Input %s not found in tria->inputs",EnumToStringx(enum_type));
    3680 
    3681         /*If we don't find it, no big deal, just don't do the transfer. Otherwise, build a new Result
    3682          * object out of the input, with the additional step and time information: */
    3683         this->results->AddObject((Object*)input->SpawnResult(step,time));
    3684         #ifdef _HAVE_CONTROL_
    3685         if(input->Enum()==ControlInputEnum) this->results->AddObject((Object*)((ControlInput*)input)->SpawnGradient(step,time));
    3686         #endif
    3687 }
    3688 /*}}}*/
    3689 /*FUNCTION Tria::InputUpdateFromConstant(int value, int name);{{{1*/
    3690 void  Tria::InputUpdateFromConstant(int constant, int name){
    3691         /*Check that name is an element input*/
    3692         if (!IsInput(name)) return;
    3693 
    3694         /*update input*/
    3695         this->inputs->AddInput(new IntInput(name,constant));
    3696 }
    3697 /*}}}*/
    3698 /*FUNCTION Tria::InputUpdateFromConstant(double value, int name);{{{1*/
    3699 void  Tria::InputUpdateFromConstant(double constant, int name){
    3700         /*Check that name is an element input*/
    3701         if (!IsInput(name)) return;
    3702 
    3703         /*update input*/
    3704         this->inputs->AddInput(new DoubleInput(name,constant));
    3705 }
    3706 /*}}}*/
    3707 /*FUNCTION Tria::InputUpdateFromConstant(bool value, int name);{{{1*/
    3708 void  Tria::InputUpdateFromConstant(bool constant, int name){
    3709         /*Check that name is an element input*/
    3710         if (!IsInput(name)) return;
    3711 
    3712         /*update input*/
    3713         this->inputs->AddInput(new BoolInput(name,constant));
    3714 }
    3715 /*}}}*/
    3716 /*FUNCTION Tria::InputUpdateFromIoModel{{{1*/
    3717 void Tria::InputUpdateFromIoModel(int index, IoModel* iomodel){ //i is the element index
    3718 
    3719         /*Intermediaries*/
    3720         int    i,j;
    3721         int    tria_vertex_ids[3];
    3722         double nodeinputs[3];
    3723         double cmmininputs[3];
    3724         double cmmaxinputs[3];
    3725         bool   control_analysis=false;
    3726         int    num_control_type;
    3727         double yts;
    3728         int    num_cm_responses;
    3729    
    3730         /*Get parameters: */
    3731         iomodel->Constant(&control_analysis,InversionIscontrolEnum);
    3732         iomodel->Constant(&num_control_type,InversionNumControlParametersEnum);
    3733         iomodel->Constant(&yts,ConstantsYtsEnum);
    3734         iomodel->Constant(&num_cm_responses,InversionNumCostFunctionsEnum);
    3735 
    3736         /*Recover vertices ids needed to initialize inputs*/
    3737         for(i=0;i<3;i++){
    3738                 tria_vertex_ids[i]=(int)iomodel->Data(MeshElementsEnum)[3*index+i]; //ids for vertices are in the elements array from Matlab
    3739         }
    3740 
    3741         /*Control Inputs*/
    3742         #ifdef _HAVE_CONTROL_
    3743         if (control_analysis && iomodel->Data(InversionControlParametersEnum)){
    3744                 for(i=0;i<num_control_type;i++){
    3745                         switch((int)iomodel->Data(InversionControlParametersEnum)[i]){
    3746                                 case BalancethicknessThickeningRateEnum:
    3747                                         if (iomodel->Data(BalancethicknessThickeningRateEnum)){
    3748                                                 for(j=0;j<3;j++)nodeinputs[j]=iomodel->Data(BalancethicknessThickeningRateEnum)[tria_vertex_ids[j]-1]/yts;
    3749                                                 for(j=0;j<3;j++)cmmininputs[j]=iomodel->Data(InversionMinParametersEnum)[(tria_vertex_ids[j]-1)*num_control_type+i]/yts;
    3750                                                 for(j=0;j<3;j++)cmmaxinputs[j]=iomodel->Data(InversionMaxParametersEnum)[(tria_vertex_ids[j]-1)*num_control_type+i]/yts;
    3751                                                 this->inputs->AddInput(new ControlInput(BalancethicknessThickeningRateEnum,TriaVertexInputEnum,nodeinputs,cmmininputs,cmmaxinputs,i+1));
    3752                                         }
    3753                                         break;
    3754                                 case VxEnum:
    3755                                         if (iomodel->Data(VxEnum)){
    3756                                                 for(j=0;j<3;j++)nodeinputs[j]=iomodel->Data(VxEnum)[tria_vertex_ids[j]-1]/yts;
    3757                                                 for(j=0;j<3;j++)cmmininputs[j]=iomodel->Data(InversionMinParametersEnum)[(tria_vertex_ids[j]-1)*num_control_type+i]/yts;
    3758                                                 for(j=0;j<3;j++)cmmaxinputs[j]=iomodel->Data(InversionMaxParametersEnum)[(tria_vertex_ids[j]-1)*num_control_type+i]/yts;
    3759                                                 this->inputs->AddInput(new ControlInput(VxEnum,TriaVertexInputEnum,nodeinputs,cmmininputs,cmmaxinputs,i+1));
    3760                                         }
    3761                                         break;
    3762                                 case VyEnum:
    3763                                         if (iomodel->Data(VyEnum)){
    3764                                                 for(j=0;j<3;j++)nodeinputs[j]=iomodel->Data(VyEnum)[tria_vertex_ids[j]-1]/yts;
    3765                                                 for(j=0;j<3;j++)cmmininputs[j]=iomodel->Data(InversionMinParametersEnum)[(tria_vertex_ids[j]-1)*num_control_type+i]/yts;
    3766                                                 for(j=0;j<3;j++)cmmaxinputs[j]=iomodel->Data(InversionMaxParametersEnum)[(tria_vertex_ids[j]-1)*num_control_type+i]/yts;
    3767                                                 this->inputs->AddInput(new ControlInput(VyEnum,TriaVertexInputEnum,nodeinputs,cmmininputs,cmmaxinputs,i+1));
    3768                                         }
    3769                                         break;
    3770                                 case FrictionCoefficientEnum:
    3771                                         if (iomodel->Data(FrictionCoefficientEnum)){
    3772                                                 for(j=0;j<3;j++)nodeinputs[j]=iomodel->Data(FrictionCoefficientEnum)[tria_vertex_ids[j]-1];
    3773                                                 for(j=0;j<3;j++)cmmininputs[j]=iomodel->Data(InversionMinParametersEnum)[(tria_vertex_ids[j]-1)*num_control_type+i];
    3774                                                 for(j=0;j<3;j++)cmmaxinputs[j]=iomodel->Data(InversionMaxParametersEnum)[(tria_vertex_ids[j]-1)*num_control_type+i];
    3775                                                 this->inputs->AddInput(new ControlInput(FrictionCoefficientEnum,TriaVertexInputEnum,nodeinputs,cmmininputs,cmmaxinputs,i+1));
    3776                                         }
    3777                                         break;
    3778                                 case MaterialsRheologyBbarEnum:
    3779                                         /*Matice will take care of it*/ break;
    3780                                 default:
    3781                                         _error_("Control %s not implemented yet",EnumToStringx((int)iomodel->Data(InversionControlParametersEnum)[i]));
    3782                         }
    3783                 }
    3784         }
    3785         #endif
    3786 
    3787         /*DatasetInputs*/
    3788         if (control_analysis && iomodel->Data(InversionCostFunctionsCoefficientsEnum)){
    3789 
    3790                 /*Create inputs and add to DataSetInput*/
    3791                 DatasetInput* datasetinput=new DatasetInput(InversionCostFunctionsCoefficientsEnum);
    3792                 for(i=0;i<num_cm_responses;i++){
    3793                         for(j=0;j<3;j++)nodeinputs[j]=iomodel->Data(InversionCostFunctionsCoefficientsEnum)[(tria_vertex_ids[j]-1)*num_cm_responses+i];
    3794                         datasetinput->inputs->AddObject(new TriaVertexInput(InversionCostFunctionsCoefficientsEnum,nodeinputs));
    3795                 }
    3796 
    3797                 /*Add datasetinput to element inputs*/
    3798                 this->inputs->AddInput(datasetinput);
    3799         }
    3800 }
    3801 /*}}}*/
    3802 /*FUNCTION Tria::InputUpdateFromSolution {{{1*/
    3803 void  Tria::InputUpdateFromSolution(double* solution){
    3804 
    3805         /*retrive parameters: */
    3806         int analysis_type;
    3807         parameters->FindParam(&analysis_type,AnalysisTypeEnum);
    3808 
    3809         /*Just branch to the correct InputUpdateFromSolution generator, according to the type of analysis we are carrying out: */
    3810         switch(analysis_type){
    3811                 case DiagnosticHorizAnalysisEnum:
    3812                         InputUpdateFromSolutionDiagnosticHoriz( solution);
     4728/*FUNCTION Tria::CreateKMatrixAdjointBalancethickness {{{1*/
     4729ElementMatrix* Tria::CreateKMatrixAdjointBalancethickness(void){
     4730
     4731        ElementMatrix* Ke=NULL;
     4732
     4733        /*Get Element Matrix of the forward model*/
     4734        switch(GetElementType()){
     4735                case P1Enum:
     4736                        Ke=CreateKMatrixBalancethickness_CG();
    38134737                        break;
    3814                 case DiagnosticHutterAnalysisEnum:
    3815                         InputUpdateFromSolutionDiagnosticHoriz( solution);
    3816                         break;
    3817                 #ifdef _HAVE_CONTROL_
    3818                 case AdjointHorizAnalysisEnum:
    3819                         InputUpdateFromSolutionAdjointHoriz( solution);
    3820                         break;
    3821                 case AdjointBalancethicknessAnalysisEnum:
    3822                         InputUpdateFromSolutionAdjointBalancethickness( solution);
    3823                         break;
    3824                 #endif
    3825                 case BedSlopeXAnalysisEnum:
    3826                         InputUpdateFromSolutionOneDof(solution,BedSlopeXEnum);
    3827                         break;
    3828                 case BedSlopeYAnalysisEnum:
    3829                         InputUpdateFromSolutionOneDof(solution,BedSlopeYEnum);
    3830                         break;
    3831                 case SurfaceSlopeXAnalysisEnum:
    3832                         InputUpdateFromSolutionOneDof(solution,SurfaceSlopeXEnum);
    3833                         break;
    3834                 case SurfaceSlopeYAnalysisEnum:
    3835                         InputUpdateFromSolutionOneDof(solution,SurfaceSlopeYEnum);
    3836                         break;
    3837                 case PrognosticAnalysisEnum:
    3838                         InputUpdateFromSolutionPrognostic(solution);
    3839                         break;
    3840                 case HydrologyAnalysisEnum:
    3841                         InputUpdateFromSolutionHydrology(solution);
    3842                         break;
    3843                 case BalancethicknessAnalysisEnum:
    3844                         InputUpdateFromSolutionOneDof(solution,ThicknessEnum);
     4738                case P1DGEnum:
     4739                        Ke=CreateKMatrixBalancethickness_DG();
    38454740                        break;
    38464741                default:
    3847                         _error_("analysis %i (%s) not supported yet",analysis_type,EnumToStringx(analysis_type));
    3848         }
    3849 }
    3850 /*}}}*/
    3851 /*FUNCTION Tria::InputUpdateFromSolutionDiagnosticHoriz {{{1*/
    3852 void  Tria::InputUpdateFromSolutionDiagnosticHoriz(double* solution){
    3853        
     4742                        _error_("Element type %s not supported yet",EnumToStringx(GetElementType()));
     4743        }
     4744
     4745        /*Transpose and return Ke*/
     4746        Ke->Transpose();
     4747        return Ke;
     4748}
     4749/*}}}*/
     4750/*FUNCTION Tria::InputUpdateFromSolutionAdjointHoriz {{{1*/
     4751void  Tria::InputUpdateFromSolutionAdjointHoriz(double* solution){
     4752
    38544753        const int numdof=NDOF2*NUMVERTICES;
    38554754
    38564755        int       i;
    3857         int       dummy;
    38584756        int*      doflist=NULL;
    3859         double    rho_ice,g;
    38604757        double    values[numdof];
    3861         double    vx[NUMVERTICES];
    3862         double    vy[NUMVERTICES];
    3863         double    vz[NUMVERTICES];
    3864         double    vel[NUMVERTICES];
    3865         double    pressure[NUMVERTICES];
    3866         double    thickness[NUMVERTICES];
    3867        
     4758        double    lambdax[NUMVERTICES];
     4759        double    lambday[NUMVERTICES];
     4760
    38684761        /*Get dof list: */
    38694762        GetDofList(&doflist,NoneApproximationEnum,GsetEnum);
     
    38744767        /*Ok, we have vx and vy in values, fill in vx and vy arrays: */
    38754768        for(i=0;i<NUMVERTICES;i++){
    3876                 vx[i]=values[i*NDOF2+0];
    3877                 vy[i]=values[i*NDOF2+1];
     4769                lambdax[i]=values[i*NDOF2+0];
     4770                lambday[i]=values[i*NDOF2+1];
    38784771
    38794772                /*Check solution*/
    3880                 if(isnan(vx[i])) _error_("NaN found in solution vector");
    3881                 if(isnan(vy[i])) _error_("NaN found in solution vector");
    3882         }
    3883 
    3884         /*Get Vz and compute vel*/
    3885         GetParameterListOnVertices(&vz[0],VzEnum,0);
    3886         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);
    3887 
    3888         /*For pressure: we have not computed pressure in this analysis, for this element. We are in 2D,
    3889          *so the pressure is just the pressure at the bedrock: */
    3890         rho_ice=matpar->GetRhoIce();
    3891         g=matpar->GetG();
    3892         GetParameterListOnVertices(&thickness[0],ThicknessEnum);
    3893         for(i=0;i<NUMVERTICES;i++) pressure[i]=rho_ice*g*thickness[i];
    3894 
    3895         /*Now, we have to move the previous Vx and Vy inputs  to old
    3896          * status, otherwise, we'll wipe them off: */
    3897         this->inputs->ChangeEnum(VxEnum,VxPicardEnum);
    3898         this->inputs->ChangeEnum(VyEnum,VyPicardEnum);
    3899         this->inputs->ChangeEnum(PressureEnum,PressurePicardEnum);
     4773                if(isnan(lambdax[i])) _error_("NaN found in solution vector");
     4774                if(isnan(lambday[i])) _error_("NaN found in solution vector");
     4775        }
    39004776
    39014777        /*Add vx and vy as inputs to the tria element: */
    3902         this->inputs->AddInput(new TriaVertexInput(VxEnum,vx));
    3903         this->inputs->AddInput(new TriaVertexInput(VyEnum,vy));
    3904         this->inputs->AddInput(new TriaVertexInput(VelEnum,vel));
    3905         this->inputs->AddInput(new TriaVertexInput(PressureEnum,pressure));
     4778        this->inputs->AddInput(new TriaVertexInput(AdjointxEnum,lambdax));
     4779        this->inputs->AddInput(new TriaVertexInput(AdjointyEnum,lambday));
    39064780
    39074781        /*Free ressources:*/
    39084782        xfree((void**)&doflist);
    3909 
    3910 }
    3911 /*}}}*/
    3912 /*FUNCTION Tria::InputUpdateFromSolutionDiagnosticHutter {{{1*/
    3913 void  Tria::InputUpdateFromSolutionDiagnosticHutter(double* solution){
    3914        
    3915         const int numdof=NDOF2*NUMVERTICES;
    3916        
     4783}
     4784/*}}}*/
     4785/*FUNCTION Tria::InputUpdateFromSolutionAdjointBalancethickness {{{1*/
     4786void  Tria::InputUpdateFromSolutionAdjointBalancethickness(double* solution){
     4787
     4788        const int numdof=NDOF1*NUMVERTICES;
     4789
    39174790        int       i;
    3918         int       dummy;
    39194791        int*      doflist=NULL;
    3920         double    rho_ice,g;
    39214792        double    values[numdof];
    3922         double    vx[NUMVERTICES];
    3923         double    vy[NUMVERTICES];
    3924         double    vz[NUMVERTICES];
    3925         double    vel[NUMVERTICES];
    3926         double    pressure[NUMVERTICES];
    3927         double    thickness[NUMVERTICES];
    3928         double*   vz_ptr=NULL;
    3929         Input*    vz_input=NULL;
    3930        
     4793        double    lambda[NUMVERTICES];
     4794
    39314795        /*Get dof list: */
    39324796        GetDofList(&doflist,NoneApproximationEnum,GsetEnum);
     
    39364800
    39374801        /*Ok, we have vx and vy in values, fill in vx and vy arrays: */
    3938         for(i=0;i<NUMVERTICES;i++){
    3939                 vx[i]=values[i*NDOF2+0];
    3940                 vy[i]=values[i*NDOF2+1];
    3941 
    3942                 /*Check solution*/
    3943                 if(isnan(vx[i])) _error_("NaN found in solution vector");
    3944                 if(isnan(vy[i])) _error_("NaN found in solution vector");
    3945         }
    3946 
    3947         /*Get Vz*/
    3948         vz_input=inputs->GetInput(VzEnum);
    3949         if (vz_input){
    3950                 if (vz_input->Enum()!=TriaVertexInputEnum){
    3951                         _error_("Cannot compute Vel as Vz is of type %s",EnumToStringx(vz_input->Enum()));
    3952                 }
    3953                 vz_input->GetValuesPtr(&vz_ptr,&dummy);
    3954                 for(i=0;i<NUMVERTICES;i++) vz[i]=vz_ptr[i];
    3955         }
    3956         else{
    3957                 for(i=0;i<NUMVERTICES;i++) vz[i]=0.0;
    3958         }
    3959 
    3960         /*Now Compute vel*/
    3961         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);
    3962 
    3963         /*For pressure: we have not computed pressure in this analysis, for this element. We are in 2D,
    3964          *so the pressure is just the pressure at the bedrock: */
    3965         rho_ice=matpar->GetRhoIce();
    3966         g=matpar->GetG();
    3967         GetParameterListOnVertices(&thickness[0],ThicknessEnum);
    3968         for(i=0;i<NUMVERTICES;i++) pressure[i]=rho_ice*g*thickness[i];
    3969 
    3970         /*Now, we have to move the previous Vx and Vy inputs  to old
    3971          * status, otherwise, we'll wipe them off: */
    3972         this->inputs->ChangeEnum(VxEnum,VxPicardEnum);
    3973         this->inputs->ChangeEnum(VyEnum,VyPicardEnum);
    3974         this->inputs->ChangeEnum(PressureEnum,PressurePicardEnum);
     4802        for(i=0;i<numdof;i++){
     4803                lambda[i]=values[i];
     4804                if(isnan(lambda[i])) _error_("NaN found in solution vector");
     4805        }
    39754806
    39764807        /*Add vx and vy as inputs to the tria element: */
    3977         this->inputs->AddInput(new TriaVertexInput(VxEnum,vx));
    3978         this->inputs->AddInput(new TriaVertexInput(VyEnum,vy));
    3979         this->inputs->AddInput(new TriaVertexInput(VelEnum,vel));
    3980         this->inputs->AddInput(new TriaVertexInput(PressureEnum,pressure));
     4808        this->inputs->AddInput(new TriaVertexInput(AdjointEnum,lambda));
    39814809
    39824810        /*Free ressources:*/
     
    39844812}
    39854813/*}}}*/
    3986 /*FUNCTION Tria::InputUpdateFromSolutionOneDof{{{1*/
    3987 void  Tria::InputUpdateFromSolutionOneDof(double* solution,int enum_type){
    3988 
    3989         const int numdof          = NDOF1*NUMVERTICES;
    3990 
    3991         int*      doflist=NULL;
    3992         double    values[numdof];
     4814#endif
     4815
     4816#ifdef _HAVE_HYDROLOGY_
     4817/*FUNCTION Tria::CreateHydrologyWaterVelocityInput {{{1*/
     4818void Tria::CreateHydrologyWaterVelocityInput(void){
     4819
     4820        /*material parameters: */
     4821        double mu_water=0.001787;  //unit= [N s/m2]
     4822        double w;
     4823        double rho_ice, rho_water, g;
     4824        double dsdx,dsdy,dbdx,dbdy;
     4825        double vx[NUMVERTICES];
     4826        double vy[NUMVERTICES];
     4827        GaussTria *gauss = NULL;
     4828
     4829        /*Retrieve all inputs and parameters*/
     4830        rho_ice=matpar->GetRhoIce();
     4831        rho_water=matpar->GetRhoWater();
     4832        g=matpar->GetG();
     4833        Input* surfaceslopex_input=inputs->GetInput(SurfaceSlopeXEnum); _assert_(surfaceslopex_input);
     4834        Input* surfaceslopey_input=inputs->GetInput(SurfaceSlopeYEnum); _assert_(surfaceslopey_input);
     4835        Input* bedslopex_input=inputs->GetInput(BedSlopeXEnum);         _assert_(bedslopex_input);
     4836        Input* bedslopey_input=inputs->GetInput(BedSlopeYEnum);         _assert_(bedslopey_input);
     4837        Input* watercolumn_input=inputs->GetInput(WatercolumnEnum);     _assert_(watercolumn_input);
     4838
     4839        gauss=new GaussTria();
     4840        for (int iv=0;iv<NUMVERTICES;iv++){
     4841                gauss->GaussVertex(iv);
     4842                surfaceslopex_input->GetParameterValue(&dsdx,gauss);
     4843                surfaceslopey_input->GetParameterValue(&dsdy,gauss);
     4844                bedslopex_input->GetParameterValue(&dbdx,gauss);
     4845                bedslopey_input->GetParameterValue(&dbdy,gauss);
     4846                watercolumn_input->GetParameterValue(&w,gauss);
     4847
     4848                /* Water velocity x and y components */
     4849                vx[iv]= - pow(w,2)/(12 * mu_water)*(rho_ice*g*dsdx+(rho_water-rho_ice)*g*dbdx);
     4850                vy[iv]= - pow(w,2)/(12 * mu_water)*(rho_ice*g*dsdy+(rho_water-rho_ice)*g*dbdy);
     4851                //vx[iv]=0.001;
     4852                //vy[iv]=0;
     4853        }
     4854
     4855        /*clean-up*/
     4856        delete gauss;
     4857
     4858        /*Add to inputs*/
     4859        this->inputs->AddInput(new TriaVertexInput(HydrologyWaterVxEnum,vx));
     4860        this->inputs->AddInput(new TriaVertexInput(HydrologyWaterVyEnum,vy));
     4861}
     4862/*}}}*/
     4863/*FUNCTION Tria::CreateKMatrixHydrology{{{1*/
     4864ElementMatrix* Tria::CreateKMatrixHydrology(void){
     4865
     4866        /*Constants*/
     4867        const int    numdof=NDOF1*NUMVERTICES;
     4868
     4869        /*Intermediaries */
     4870        int        artdiff;
     4871        int        i,j,ig;
     4872        double     Jdettria,DL_scalar,dt,h;
     4873        double     vx,vy,vel,dvxdx,dvydy;
     4874        double     dvx[2],dvy[2];
     4875        double     v_gauss[2]={0.0};
     4876        double     xyz_list[NUMVERTICES][3];
     4877        double     L[NUMVERTICES];
     4878        double     B[2][NUMVERTICES];
     4879        double     Bprime[2][NUMVERTICES];
     4880        double     K[2][2]                        ={0.0};
     4881        double     KDL[2][2]                      ={0.0};
     4882        double     DL[2][2]                        ={0.0};
     4883        double     DLprime[2][2]                   ={0.0};
     4884        GaussTria *gauss=NULL;
     4885
     4886        /*Initialize Element matrix*/
     4887        ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,NoneApproximationEnum);
     4888
     4889        /*Create water velocity vx and vy from current inputs*/
     4890        CreateHydrologyWaterVelocityInput();
     4891
     4892        /*Retrieve all inputs and parameters*/
     4893        GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
     4894        this->parameters->FindParam(&dt,TimesteppingTimeStepEnum);
     4895        this->parameters->FindParam(&artdiff,HydrologyStabilizationEnum);
     4896        Input* vx_input=inputs->GetInput(HydrologyWaterVxEnum); _assert_(vx_input);
     4897        Input* vy_input=inputs->GetInput(HydrologyWaterVyEnum); _assert_(vy_input);
     4898        h=this->GetArea();
     4899
     4900        /* Start  looping on the number of gaussian points: */
     4901        gauss=new GaussTria(2);
     4902        for (ig=gauss->begin();ig<gauss->end();ig++){
     4903
     4904                gauss->GaussPoint(ig);
     4905
     4906                GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss);
     4907                GetL(&L[0], &xyz_list[0][0], gauss,NDOF1);
     4908
     4909                vx_input->GetParameterValue(&vx,gauss);
     4910                vy_input->GetParameterValue(&vy,gauss);
     4911                vx_input->GetParameterDerivativeValue(&dvx[0],&xyz_list[0][0],gauss);
     4912                vy_input->GetParameterDerivativeValue(&dvy[0],&xyz_list[0][0],gauss);
     4913
     4914                DL_scalar=gauss->weight*Jdettria;
     4915
     4916                TripleMultiply( &L[0],1,numdof,1,
     4917                                        &DL_scalar,1,1,0,
     4918                                        &L[0],1,numdof,0,
     4919                                        &Ke->values[0],1);
     4920
     4921                GetBPrognostic(&B[0][0], &xyz_list[0][0], gauss);
     4922                GetBprimePrognostic(&Bprime[0][0], &xyz_list[0][0], gauss);
     4923
     4924                dvxdx=dvx[0];
     4925                dvydy=dvy[1];
     4926                DL_scalar=dt*gauss->weight*Jdettria;
     4927
     4928                DL[0][0]=DL_scalar*dvxdx;
     4929                DL[1][1]=DL_scalar*dvydy;
     4930                DLprime[0][0]=DL_scalar*vx;
     4931                DLprime[1][1]=DL_scalar*vy;
     4932
     4933                TripleMultiply( &B[0][0],2,numdof,1,
     4934                                        &DL[0][0],2,2,0,
     4935                                        &B[0][0],2,numdof,0,
     4936                                        &Ke->values[0],1);
     4937
     4938                TripleMultiply( &B[0][0],2,numdof,1,
     4939                                        &DLprime[0][0],2,2,0,
     4940                                        &Bprime[0][0],2,numdof,0,
     4941                                        &Ke->values[0],1);
     4942
     4943                if(artdiff){
     4944                        vel=sqrt(pow(vx,2.)+pow(vy,2.));
     4945                        K[0][0]=h/(2*vel)*vx*vx;
     4946                        K[1][0]=h/(2*vel)*vy*vx;
     4947                        K[0][1]=h/(2*vel)*vx*vy;
     4948                        K[1][1]=h/(2*vel)*vy*vy;
     4949                        KDL[0][0]=DL_scalar*K[0][0];
     4950                        KDL[1][0]=DL_scalar*K[1][0];
     4951                        KDL[0][1]=DL_scalar*K[0][1];
     4952                        KDL[1][1]=DL_scalar*K[1][1];
     4953
     4954                        TripleMultiply( &Bprime[0][0],2,numdof,1,
     4955                                                &KDL[0][0],2,2,0,
     4956                                                &Bprime[0][0],2,numdof,0,
     4957                                                &Ke->values[0],1);
     4958                }
     4959        }
     4960
     4961        /*Clean up and return*/
     4962        delete gauss;
     4963        return Ke;
     4964}
     4965/*}}}*/
     4966/*FUNCTION Tria::CreatePVectorHydrology {{{1*/
     4967ElementVector* Tria::CreatePVectorHydrology(void){
     4968
     4969        /*Constants*/
     4970        const int    numdof=NDOF1*NUMVERTICES;
     4971
     4972        /*Intermediaries */
     4973        int        i,j,ig;
     4974        double     Jdettria,dt;
     4975        double     basal_melting_g;
     4976        double     old_watercolumn_g;
     4977        double     xyz_list[NUMVERTICES][3];
     4978        double     basis[numdof];
     4979        GaussTria* gauss=NULL;
     4980
     4981        /*Initialize Element vector*/
     4982        ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters);
     4983
     4984        /*Retrieve all inputs and parameters*/
     4985        GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
     4986        this->parameters->FindParam(&dt,TimesteppingTimeStepEnum);
     4987        Input* basal_melting_input=inputs->GetInput(BasalforcingsMeltingRateEnum); _assert_(basal_melting_input);
     4988        Input* old_watercolumn_input=inputs->GetInput(WaterColumnOldEnum);         _assert_(old_watercolumn_input);
     4989
     4990        /*Initialize basal_melting_correction_g to 0, do not forget!:*/
     4991        /* Start  looping on the number of gaussian points: */
     4992        gauss=new GaussTria(2);
     4993        for(ig=gauss->begin();ig<gauss->end();ig++){
     4994
     4995                gauss->GaussPoint(ig);
     4996
     4997                GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss);
     4998                GetNodalFunctions(basis, gauss);
     4999
     5000                basal_melting_input->GetParameterValue(&basal_melting_g,gauss);
     5001                old_watercolumn_input->GetParameterValue(&old_watercolumn_g,gauss);
     5002
     5003                if(dt)for(i=0;i<numdof;i++) pe->values[i]+=Jdettria*gauss->weight*(old_watercolumn_g+dt*basal_melting_g)*basis[i];
     5004                else  for(i=0;i<numdof;i++) pe->values[i]+=Jdettria*gauss->weight*basal_melting_g*basis[i];
     5005        }
     5006               
     5007        /*Clean up and return*/
     5008        delete gauss;
     5009        return pe;
     5010}
     5011/*}}}*/
     5012/*FUNCTION Tria::GetSolutionFromInputsHydrology{{{1*/
     5013void  Tria::GetSolutionFromInputsHydrology(Vec solution){
     5014
     5015        const int    numdof=NDOF1*NUMVERTICES;
     5016
     5017        int i,dummy;
     5018        int*         doflist=NULL;
     5019        double       watercolumn;
     5020        double       values[numdof];
     5021        GaussTria*   gauss=NULL;
    39935022
    39945023        /*Get dof list: */
    39955024        GetDofList(&doflist,NoneApproximationEnum,GsetEnum);
    39965025
    3997         /*Use the dof list to index into the solution vector: */
    3998         for(int i=0;i<numdof;i++){
    3999                 values[i]=solution[doflist[i]];
    4000                 if(isnan(values[i])) _error_("NaN found in solution vector");
    4001         }
    4002 
    4003         /*Add input to the element: */
    4004         this->inputs->AddInput(new TriaVertexInput(enum_type,values));
     5026        /*Get inputs*/
     5027        Input* watercolumn_input=inputs->GetInput(WatercolumnEnum); _assert_(watercolumn_input);
     5028
     5029        /*Ok, we have watercolumn values, fill in watercolumn array: */
     5030        /*P1 element only for now*/
     5031        gauss=new GaussTria();
     5032        for(i=0;i<NUMVERTICES;i++){
     5033
     5034                gauss->GaussVertex(i);
     5035
     5036                /*Recover watercolumn*/
     5037                watercolumn_input->GetParameterValue(&watercolumn,gauss);
     5038                values[i]=watercolumn;
     5039        }
     5040
     5041        VecSetValues(solution,numdof,doflist,(const double*)values,INSERT_VALUES);
    40055042
    40065043        /*Free ressources:*/
    4007         xfree((void**)&doflist);
    4008 }
    4009 /*}}}*/
    4010 /*FUNCTION Tria::InputUpdateFromSolutionPrognostic{{{1*/
    4011 void  Tria::InputUpdateFromSolutionPrognostic(double* solution){
    4012 
    4013         /*Intermediaries*/
    4014         const int numdof = NDOF1*NUMVERTICES;
    4015 
    4016         int       i,dummy,hydroadjustment;
    4017         int*      doflist=NULL;
    4018         double    rho_ice,rho_water;
    4019         double    values[numdof];
    4020         double    bed[numdof];
    4021         double    surface[numdof];
    4022         double    *bed_ptr = NULL;
    4023         double    *thickness_ptr = NULL;
    4024         double    *surface_ptr = NULL;
    4025 
    4026         /*Get dof list: */
    4027         GetDofList(&doflist,NoneApproximationEnum,GsetEnum);
    4028 
    4029         /*Use the dof list to index into the solution vector: */
    4030         for(i=0;i<numdof;i++){
    4031                 values[i]=solution[doflist[i]];
    4032                 if(isnan(values[i])) _error_("NaN found in solution vector");
    4033                 /*Constrain thickness to be at least 1m*/
    4034                 if(values[i]<1) values[i]=1;
    4035         }
    4036 
    4037         /*Get previous bed, thickness and surface*/
    4038         Input* bed_input=inputs->GetInput(BedEnum);             _assert_(bed_input);
    4039         Input* thickness_input=inputs->GetInput(ThicknessEnum); _assert_(thickness_input);
    4040         Input* surface_input=inputs->GetInput(SurfaceEnum);     _assert_(surface_input);
    4041         bed_input->GetValuesPtr(&bed_ptr,&dummy);
    4042         thickness_input->GetValuesPtr(&thickness_ptr,&dummy);
    4043         surface_input->GetValuesPtr(&surface_ptr,&dummy);
    4044 
    4045         /*Fing PrognosticHydrostaticAdjustment to figure out how to update the geometry:*/
    4046         this->parameters->FindParam(&hydroadjustment,PrognosticHydrostaticAdjustmentEnum);
    4047 
    4048         /*recover material parameters: */
    4049         rho_ice=matpar->GetRhoIce();
    4050         rho_water=matpar->GetRhoWater();
    4051 
    4052         for(i=0;i<numdof;i++) {
    4053                 /*If shelf: hydrostatic equilibrium*/
    4054                 if (this->nodes[i]->IsOnSheet()){
    4055                         surface[i]=bed_ptr[i]+values[i]; //surface=oldbed+newthickness
    4056                         bed[i]=bed_ptr[i]; //do nothing
    4057                 }
    4058                 else{ //this is an ice shelf
    4059 
    4060                         if(hydroadjustment==AbsoluteEnum){
    4061                                 surface[i]=values[i]*(1-rho_ice/rho_water);
    4062                                 bed[i]=values[i]*(-rho_ice/rho_water);
    4063                         }
    4064                         else if(hydroadjustment==IncrementalEnum){
    4065                                 surface[i]=surface_ptr[i]+(1.0-rho_ice/rho_water)*(values[i]-thickness_ptr[i]); //surface = oldsurface + (1-di) * dH
    4066                                 bed[i]=bed_ptr[i]-rho_ice/rho_water*(values[i]-thickness_ptr[i]); //bed = oldbed + di * dH
    4067                         }
    4068                         else _error_("Hydrostatic adjustment %i (%s) not supported yet",hydroadjustment,EnumToStringx(hydroadjustment));
    4069                 }
    4070         }
    4071 
    4072         /*Add input to the element: */
    4073         this->inputs->AddInput(new TriaVertexInput(ThicknessEnum,values));
    4074         this->inputs->AddInput(new TriaVertexInput(SurfaceEnum,surface));
    4075         this->inputs->AddInput(new TriaVertexInput(BedEnum,bed));
    4076 
    4077         /*Free ressources:*/
     5044        delete gauss;
    40785045        xfree((void**)&doflist);
    40795046}
     
    41075074}
    41085075/*}}}*/
    4109 /*FUNCTION Tria::InputUpdateFromVector(double* vector, int name, int type);{{{1*/
    4110 void  Tria::InputUpdateFromVector(double* vector, int name, int type){
    4111 
    4112         /*Check that name is an element input*/
    4113         if (!IsInput(name)) return;
    4114 
    4115         switch(type){
    4116 
    4117                 case VertexEnum:
    4118 
    4119                         /*New TriaVertexInput*/
    4120                         double values[3];
    4121 
    4122                         /*Get values on the 3 vertices*/
    4123                         for (int i=0;i<3;i++){
    4124                                 values[i]=vector[this->nodes[i]->GetVertexDof()];
    4125                         }
    4126 
    4127                         /*update input*/
    4128                         if (name==MaterialsRheologyBbarEnum || name==MaterialsRheologyBEnum){
    4129                                 matice->inputs->AddInput(new TriaVertexInput(name,values));
    4130                         }
    4131                         else{
    4132                                 this->inputs->AddInput(new TriaVertexInput(name,values));
    4133                         }
    4134                         return;
    4135 
    4136                 default:
    4137                         _error_("type %i (%s) not implemented yet",type,EnumToStringx(type));
    4138         }
    4139 }
    4140 /*}}}*/
    4141 /*FUNCTION Tria::InputUpdateFromVector(int* vector, int name, int type);{{{1*/
    4142 void  Tria::InputUpdateFromVector(int* vector, int name, int type){
    4143         _error_(" not supported yet!");
    4144 }
    4145 /*}}}*/
    4146 /*FUNCTION Tria::InputUpdateFromVector(bool* vector, int name, int type);{{{1*/
    4147 void  Tria::InputUpdateFromVector(bool* vector, int name, int type){
    4148         _error_(" not supported yet!");
    4149 }
    4150 /*}}}*/
    4151 
     5076#endif
    41525077
    41535078#ifdef _HAVE_DAKOTA_
     
    42655190/*}}}*/
    42665191#endif
    4267 /*FUNCTION Tria::InputCreate(double scalar,int enum,int code);{{{1*/
    4268 void Tria::InputCreate(double scalar,int name,int code){
    4269 
    4270         /*Check that name is an element input*/
    4271         if (!IsInput(name)) return;
    4272        
    4273         if ((code==5) || (code==1)){ //boolean
    4274                 this->inputs->AddInput(new BoolInput(name,(bool)scalar));
    4275         }
    4276         else if ((code==6) || (code==2)){ //integer
    4277                 this->inputs->AddInput(new IntInput(name,(int)scalar));
    4278         }
    4279         else if ((code==7) || (code==3)){ //double
    4280                 this->inputs->AddInput(new DoubleInput(name,(int)scalar));
    4281         }
    4282         else _error_("%s%i"," could not recognize nature of vector from code ",code);
    4283 
    4284 }
    4285 /*}}}*/
    4286 /*FUNCTION Tria::InputCreate(double* vector,int index,IoModel* iomodel,int M,int N,int vector_type,int vector_enum,int code){{{1*/
    4287 void Tria::InputCreate(double* vector, int index,IoModel* iomodel,int M,int N,int vector_type,int vector_enum,int code){//index into elements
     5192
     5193#ifdef _HAVE_BALANCED_
     5194/*FUNCTION Tria::CreateKMatrixBalancethickness {{{1*/
     5195ElementMatrix* Tria::CreateKMatrixBalancethickness(void){
     5196
     5197        switch(GetElementType()){
     5198                case P1Enum:
     5199                        return CreateKMatrixBalancethickness_CG();
     5200                case P1DGEnum:
     5201                        return CreateKMatrixBalancethickness_DG();
     5202                default:
     5203                        _error_("Element type %s not supported yet",EnumToStringx(GetElementType()));
     5204        }
     5205
     5206}
     5207/*}}}*/
     5208/*FUNCTION Tria::CreateKMatrixBalancethickness_CG {{{1*/
     5209ElementMatrix* Tria::CreateKMatrixBalancethickness_CG(void){
     5210
     5211        /*Constants*/
     5212        const int    numdof=NDOF1*NUMVERTICES;
     5213
     5214        /*Intermediaries */
     5215        int        stabilization;
     5216        int        i,j,ig,dim;
     5217        double     Jdettria,vx,vy,dvxdx,dvydy,vel,h;
     5218        double     dvx[2],dvy[2];
     5219        double     xyz_list[NUMVERTICES][3];
     5220        double     L[NUMVERTICES];
     5221        double     B[2][NUMVERTICES];
     5222        double     Bprime[2][NUMVERTICES];
     5223        double     K[2][2]                          = {0.0};
     5224        double     KDL[2][2]                        = {0.0};
     5225        double     DL[2][2]                         = {0.0};
     5226        double     DLprime[2][2]                    = {0.0};
     5227        double     DL_scalar;
     5228        GaussTria *gauss                            = NULL;
     5229
     5230        /*Initialize Element matrix*/
     5231        ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,NoneApproximationEnum);
     5232
     5233        /*Retrieve all Inputs and parameters: */
     5234        GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
     5235        this->parameters->FindParam(&stabilization,BalancethicknessStabilizationEnum);
     5236        this->parameters->FindParam(&dim,MeshDimensionEnum);
     5237        Input* vxaverage_input=NULL;
     5238        Input* vyaverage_input=NULL;
     5239        if(dim==2){
     5240                vxaverage_input=inputs->GetInput(VxEnum); _assert_(vxaverage_input);
     5241                vyaverage_input=inputs->GetInput(VyEnum); _assert_(vyaverage_input);
     5242        }
     5243        else{
     5244                vxaverage_input=inputs->GetInput(VxAverageEnum); _assert_(vxaverage_input);
     5245                vyaverage_input=inputs->GetInput(VyAverageEnum); _assert_(vyaverage_input);
     5246        }
     5247        h=sqrt(2*this->GetArea());
     5248
     5249        ///*Create Artificial diffusivity once for all if requested*/
     5250        //if(stabilization){
     5251        //      gauss=new GaussTria();
     5252        //      gauss->GaussCenter();
     5253        //      GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss);
     5254        //      delete gauss;
     5255
     5256        //      vxaverage_input->GetParameterAverage(&vx);
     5257        //      vyaverage_input->GetParameterAverage(&vy);
     5258        //      K[0][0]=pow(Jdettria,(double).5)/2.0*fabs(vx);
     5259        //      K[1][1]=pow(Jdettria,(double).5)/2.0*fabs(vy);
     5260        //}
     5261
     5262        /*Start looping on the number of gaussian points:*/
     5263        gauss=new GaussTria(2);
     5264        for (ig=gauss->begin();ig<gauss->end();ig++){
     5265
     5266                gauss->GaussPoint(ig);
     5267
     5268                GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss);
     5269                GetBPrognostic(&B[0][0], &xyz_list[0][0], gauss);
     5270                GetBprimePrognostic(&Bprime[0][0], &xyz_list[0][0], gauss);
     5271
     5272                vxaverage_input->GetParameterValue(&vx,gauss);
     5273                vyaverage_input->GetParameterValue(&vy,gauss);
     5274                vxaverage_input->GetParameterDerivativeValue(&dvx[0],&xyz_list[0][0],gauss);
     5275                vyaverage_input->GetParameterDerivativeValue(&dvy[0],&xyz_list[0][0],gauss);
     5276
     5277                dvxdx=dvx[0];
     5278                dvydy=dvy[1];
     5279                DL_scalar=gauss->weight*Jdettria;
     5280
     5281                DL[0][0]=DL_scalar*dvxdx;
     5282                DL[1][1]=DL_scalar*dvydy;
     5283
     5284                DLprime[0][0]=DL_scalar*vx;
     5285                DLprime[1][1]=DL_scalar*vy;
     5286
     5287                TripleMultiply( &B[0][0],2,numdof,1,
     5288                                        &DL[0][0],2,2,0,
     5289                                        &B[0][0],2,numdof,0,
     5290                                        &Ke->values[0],1);
     5291
     5292                TripleMultiply( &B[0][0],2,numdof,1,
     5293                                        &DLprime[0][0],2,2,0,
     5294                                        &Bprime[0][0],2,numdof,0,
     5295                                        &Ke->values[0],1);
     5296
     5297                if(stabilization==1){
     5298                        vel=sqrt(pow(vx,2.)+pow(vy,2.));
     5299                        K[0][0]=h/(2*vel)*vx*vx;
     5300                        K[1][0]=h/(2*vel)*vy*vx;
     5301                        K[0][1]=h/(2*vel)*vx*vy;
     5302                        K[1][1]=h/(2*vel)*vy*vy;
     5303                        KDL[0][0]=DL_scalar*K[0][0];
     5304                        KDL[1][0]=DL_scalar*K[1][0];
     5305                        KDL[0][1]=DL_scalar*K[0][1];
     5306                        KDL[1][1]=DL_scalar*K[1][1];
     5307
     5308                        //KDL[0][0]=DL_scalar*K[0][0];
     5309                        //KDL[1][1]=DL_scalar*K[1][1];
     5310
     5311                        TripleMultiply( &Bprime[0][0],2,numdof,1,
     5312                                                &KDL[0][0],2,2,0,
     5313                                                &Bprime[0][0],2,numdof,0,
     5314                                                &Ke->values[0],1);
     5315                }
     5316        }
     5317
     5318        /*Clean up and return*/
     5319        delete gauss;
     5320        return Ke;
     5321}
     5322/*}}}*/
     5323/*FUNCTION Tria::CreateKMatrixBalancethickness_DG {{{1*/
     5324ElementMatrix* Tria::CreateKMatrixBalancethickness_DG(void){
     5325
     5326        /*Constants*/
     5327        const int  numdof=NDOF1*NUMVERTICES;
    42885328
    42895329        /*Intermediaries*/
    4290         int    i,j,t;
    4291         int    tria_vertex_ids[3];
    4292         int    row;
    4293         double nodeinputs[3];
    4294         double time;
    4295         TransientInput* transientinput=NULL;
    4296         int    numberofvertices;
    4297         int    numberofelements;
    4298         double yts;
    4299 
    4300 
    4301         /*Fetch parameters: */
    4302         iomodel->Constant(&numberofvertices,MeshNumberofverticesEnum);
    4303         iomodel->Constant(&numberofelements,MeshNumberofelementsEnum);
    4304         iomodel->Constant(&yts,ConstantsYtsEnum);
    4305 
    4306         /*Branch on type of vector: nodal or elementary: */
    4307         if(vector_type==1){ //nodal vector
    4308 
    4309                 /*Recover vertices ids needed to initialize inputs*/
    4310                 for(i=0;i<3;i++){
    4311                         tria_vertex_ids[i]=(int)iomodel->Data(MeshElementsEnum)[3*index+i]; //ids for vertices are in the elements array from Matlab
    4312                 }
    4313 
    4314                 /*Are we in transient or static? */
    4315                 if(M==numberofvertices){
    4316 
    4317                         /*create input values: */
    4318                         for(i=0;i<3;i++)nodeinputs[i]=(double)vector[tria_vertex_ids[i]-1];
    4319 
    4320                         /*process units: */
    4321                         UnitConversion(&nodeinputs[0], 3 ,ExtToIuEnum, vector_enum);
    4322 
    4323                         /*create static input: */
    4324                         this->inputs->AddInput(new TriaVertexInput(vector_enum,nodeinputs));
    4325                 }
    4326                 else if(M==numberofvertices+1){
    4327                         /*create transient input: */
    4328                         for(t=0;t<N;t++){ //N is the number of times
    4329 
    4330                                 /*create input values: */
    4331                                 for(i=0;i<3;i++){
    4332                                         row=tria_vertex_ids[i]-1;
    4333                                         nodeinputs[i]=(double)vector[N*row+t];
    4334                                 }
    4335 
    4336                                 /*process units: */
    4337                                 UnitConversion(&nodeinputs[0], 3 ,ExtToIuEnum, vector_enum);
    4338 
    4339                                 /*time? :*/
    4340                                 time=(double)vector[(M-1)*N+t]*yts;
    4341 
    4342                                 if(t==0) transientinput=new TransientInput(vector_enum);
    4343                                 transientinput->AddTimeInput(new TriaVertexInput(vector_enum,nodeinputs),time);
    4344                         }
    4345                         this->inputs->AddInput(transientinput);
    4346                 }
    4347                 else _error_("nodal vector is either numberofnodes (%i), or numberofnodes+1 long. Field provided is %i long",numberofvertices,M);
    4348         }
    4349         else if(vector_type==2){ //element vector
    4350                 /*Are we in transient or static? */
    4351                 if(M==numberofelements){
    4352 
    4353                         /*static mode: create an input out of the element value: */
    4354 
    4355                         if (code==5){ //boolean
    4356                                 this->inputs->AddInput(new BoolInput(vector_enum,(bool)vector[index]));
    4357                         }
    4358                         else if (code==6){ //integer
    4359                                 this->inputs->AddInput(new IntInput(vector_enum,(int)vector[index]));
    4360                         }
    4361                         else if (code==7){ //double
    4362                                 this->inputs->AddInput(new DoubleInput(vector_enum,(double)vector[index]));
    4363                         }
    4364                         else _error_("%s%i"," could not recognize nature of vector from code ",code);
    4365                 }
    4366                 else {
    4367                         _error_("transient elementary inputs not supported yet!");
    4368                 }
    4369         }
    4370         else{
    4371                 _error_("Cannot add input for vector type %i (not supported)",vector_type);
    4372         }
    4373 
    4374 }
    4375 /*}}}*/
    4376 /*FUNCTION Tria::IsInput{{{1*/
    4377 bool Tria::IsInput(int name){
    4378         if (
    4379                                 name==ThicknessEnum ||
    4380                                 name==SurfaceEnum ||
    4381                                 name==BedEnum ||
    4382                                 name==SurfaceSlopeXEnum ||
    4383                                 name==SurfaceSlopeYEnum ||
    4384                                 name==BasalforcingsMeltingRateEnum ||
    4385                                 name==WatercolumnEnum ||
    4386                                 name==SurfaceforcingsMassBalanceEnum ||
    4387                                 name==SurfaceAreaEnum||
    4388                                 name==VxEnum ||
    4389                                 name==VyEnum ||
    4390                                 name==InversionVxObsEnum ||
    4391                                 name==InversionVyObsEnum ||
    4392                                 name==FrictionCoefficientEnum ||
    4393                                 name==GradientEnum ||
    4394                                 name==OldGradientEnum
    4395                 ){
    4396                 return true;
    4397         }
    4398         else return false;
    4399 }
    4400 /*}}}*/
    4401 /*FUNCTION Tria::IsOnBed {{{1*/
    4402 bool Tria::IsOnBed(){
    4403        
    4404         bool onbed;
    4405         inputs->GetParameterValue(&onbed,MeshElementonbedEnum);
    4406         return onbed;
    4407 }
    4408 /*}}}*/
    4409 /*FUNCTION Tria::IsOnShelf {{{1*/
    4410 bool   Tria::IsOnShelf(){
    4411 
    4412         bool shelf;
    4413         inputs->GetParameterValue(&shelf,MaskElementonfloatingiceEnum);
    4414         return shelf;
    4415 }
    4416 /*}}}*/
    4417 /*FUNCTION Tria::IsNodeOnShelf {{{1*/
    4418 bool   Tria::IsNodeOnShelf(){
    4419 
    4420         int  i;
    4421         bool shelf=false;
    4422 
    4423         for(i=0;i<3;i++){
    4424                 if (nodes[i]->IsOnShelf()){
    4425                         shelf=true;
    4426                         break;
    4427                 }
    4428         }
    4429         return shelf;
    4430 }
    4431 /*}}}*/
    4432 /*FUNCTION Tria::IsNodeOnShelfFromFlags {{{1*/
    4433 bool   Tria::IsNodeOnShelfFromFlags(double* flags){
    4434 
    4435         int  i;
    4436         bool shelf=false;
    4437 
    4438         for(i=0;i<3;i++){
    4439                 if (flags[nodes[i]->Sid()]){
    4440                         shelf=true;
    4441                         break;
    4442                 }
    4443         }
    4444         return shelf;
    4445 }
    4446 /*}}}*/
    4447 /*FUNCTION Tria::IsOnWater {{{1*/
    4448 bool   Tria::IsOnWater(){
    4449 
    4450         bool water;
    4451         inputs->GetParameterValue(&water,MaskElementonwaterEnum);
    4452         return water;
    4453 }
    4454 /*}}}*/
    4455 /*FUNCTION Tria::MassFlux {{{1*/
    4456 double Tria::MassFlux( double* segment,bool process_units){
    4457 
    4458         const int    numdofs=2;
    4459 
    4460         int        i;
    4461         double     mass_flux=0;
     5330        int        i,j,ig,dim;
     5331        double     vx,vy,Jdettria;
    44625332        double     xyz_list[NUMVERTICES][3];
    4463         double     normal[2];
    4464         double     length,rho_ice;
    4465         double     x1,y1,x2,y2,h1,h2;
    4466         double     vx1,vx2,vy1,vy2;
    4467         GaussTria* gauss_1=NULL;
    4468         GaussTria* gauss_2=NULL;
    4469 
    4470         /*Get material parameters :*/
    4471         rho_ice=matpar->GetRhoIce();
    4472 
    4473         /*First off, check that this segment belongs to this element: */
    4474         if ((int)*(segment+4)!=this->id)_error_("%s%i%s%i","error message: segment with id ",(int)*(segment+4)," does not belong to element with id:",this->id);
    4475 
    4476         /*Recover segment node locations: */
    4477         x1=*(segment+0); y1=*(segment+1); x2=*(segment+2); y2=*(segment+3);
    4478 
    4479         /*Get xyz list: */
     5333        double     B[2][NUMVERTICES];
     5334        double     Bprime[2][NUMVERTICES];
     5335        double     DL[2][2]={0.0};
     5336        double     DL_scalar;
     5337        GaussTria  *gauss=NULL;
     5338
     5339        /*Initialize Element matrix*/
     5340        ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,NoneApproximationEnum);
     5341
     5342        /*Retrieve all inputs and parameters*/
    44805343        GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
    4481 
    4482         /*get area coordinates of 0 and 1 locations: */
    4483         gauss_1=new GaussTria();
    4484         gauss_1->GaussFromCoords(x1,y1,&xyz_list[0][0]);
    4485         gauss_2=new GaussTria();
    4486         gauss_2->GaussFromCoords(x2,y2,&xyz_list[0][0]);
    4487 
    4488         normal[0]=cos(atan2(x1-x2,y2-y1));
    4489         normal[1]=sin(atan2(x1-x2,y2-y1));
    4490 
    4491         length=sqrt(pow(x2-x1,2.0)+pow(y2-y1,2));
    4492 
    4493         Input* thickness_input=inputs->GetInput(ThicknessEnum); _assert_(thickness_input);
     5344        this->parameters->FindParam(&dim,MeshDimensionEnum);
    44945345        Input* vx_input=inputs->GetInput(VxEnum); _assert_(vx_input);
    44955346        Input* vy_input=inputs->GetInput(VyEnum); _assert_(vy_input);
    44965347
    4497         thickness_input->GetParameterValue(&h1, gauss_1);
    4498         thickness_input->GetParameterValue(&h2, gauss_2);
    4499         vx_input->GetParameterValue(&vx1,gauss_1);
    4500         vx_input->GetParameterValue(&vx2,gauss_2);
    4501         vy_input->GetParameterValue(&vy1,gauss_1);
    4502         vy_input->GetParameterValue(&vy2,gauss_2);
    4503 
    4504         mass_flux= rho_ice*length*( 
    4505                                 (ONETHIRD*(h1-h2)*(vx1-vx2)+0.5*h2*(vx1-vx2)+0.5*(h1-h2)*vx2+h2*vx2)*normal[0]+
    4506                                 (ONETHIRD*(h1-h2)*(vy1-vy2)+0.5*h2*(vy1-vy2)+0.5*(h1-h2)*vy2+h2*vy2)*normal[1]
    4507                                 );
    4508 
    4509         /*Process units: */
    4510         mass_flux=UnitConversion(mass_flux,IuToExtEnum,MassFluxEnum);
    4511 
    4512         /*clean up and return:*/
    4513         delete gauss_1;
    4514         delete gauss_2;
    4515         return mass_flux;
    4516 }
    4517 /*}}}*/
    4518 /*FUNCTION Tria::MaxAbsVx{{{1*/
    4519 void  Tria::MaxAbsVx(double* pmaxabsvx, bool process_units){
    4520 
    4521         /*Get maximum:*/
    4522         double maxabsvx=this->inputs->MaxAbs(VxEnum);
    4523 
    4524         /*process units if requested: */
    4525         if(process_units) maxabsvx=UnitConversion(maxabsvx,IuToExtEnum,VxEnum);
    4526 
    4527         /*Assign output pointers:*/
    4528         *pmaxabsvx=maxabsvx;
    4529 }
    4530 /*}}}*/
    4531 /*FUNCTION Tria::MaxAbsVy{{{1*/
    4532 void  Tria::MaxAbsVy(double* pmaxabsvy, bool process_units){
    4533 
    4534         /*Get maximum:*/
    4535         double maxabsvy=this->inputs->MaxAbs(VyEnum);
    4536 
    4537         /*process units if requested: */
    4538         if(process_units) maxabsvy=UnitConversion(maxabsvy,IuToExtEnum,VyEnum);
    4539 
    4540         /*Assign output pointers:*/
    4541         *pmaxabsvy=maxabsvy;
    4542 }
    4543 /*}}}*/
    4544 /*FUNCTION Tria::MaxAbsVz{{{1*/
    4545 void  Tria::MaxAbsVz(double* pmaxabsvz, bool process_units){
    4546 
    4547         /*Get maximum:*/
    4548         double maxabsvz=this->inputs->MaxAbs(VzEnum);
    4549 
    4550         /*process units if requested: */
    4551         if(process_units) maxabsvz=UnitConversion(maxabsvz,IuToExtEnum,VyEnum);
    4552 
    4553         /*Assign output pointers:*/
    4554         *pmaxabsvz=maxabsvz;
    4555 }
    4556 /*}}}*/
    4557 /*FUNCTION Tria::MaxVel{{{1*/
    4558 void  Tria::MaxVel(double* pmaxvel, bool process_units){
    4559 
    4560         /*Get maximum:*/
    4561         double maxvel=this->inputs->Max(VelEnum);
    4562 
    4563         /*process units if requested: */
    4564         if(process_units) maxvel=UnitConversion(maxvel,IuToExtEnum,VelEnum);
    4565 
    4566         /*Assign output pointers:*/
    4567         *pmaxvel=maxvel;
    4568 }
    4569 /*}}}*/
    4570 /*FUNCTION Tria::MaxVx{{{1*/
    4571 void  Tria::MaxVx(double* pmaxvx, bool process_units){
    4572 
    4573         /*Get maximum:*/
    4574         double maxvx=this->inputs->Max(VxEnum);
    4575 
    4576         /*process units if requested: */
    4577         if(process_units) maxvx=UnitConversion(maxvx,IuToExtEnum,VxEnum);
    4578 
    4579         /*Assign output pointers:*/
    4580         *pmaxvx=maxvx;
    4581 }
    4582 /*}}}*/
    4583 /*FUNCTION Tria::MaxVy{{{1*/
    4584 void  Tria::MaxVy(double* pmaxvy, bool process_units){
    4585 
    4586         /*Get maximum:*/
    4587         double maxvy=this->inputs->Max(VyEnum);
    4588 
    4589         /*process units if requested: */
    4590         if(process_units) maxvy=UnitConversion(maxvy,IuToExtEnum,VyEnum);
    4591 
    4592         /*Assign output pointers:*/
    4593         *pmaxvy=maxvy;
    4594 
    4595 }
    4596 /*}}}*/
    4597 /*FUNCTION Tria::MaxVz{{{1*/
    4598 void  Tria::MaxVz(double* pmaxvz, bool process_units){
    4599 
    4600         /*Get maximum:*/
    4601         double maxvz=this->inputs->Max(VzEnum);
    4602 
    4603         /*process units if requested: */
    4604         if(process_units) maxvz=UnitConversion(maxvz,IuToExtEnum,VzEnum);
    4605 
    4606         /*Assign output pointers:*/
    4607         *pmaxvz=maxvz;
    4608 }
    4609 /*}}}*/
    4610 /*FUNCTION Tria::MigrateGroundingLine{{{1*/
    4611 void  Tria::MigrateGroundingLine(void){
    4612 
    4613 
    4614         double *values         = NULL;
    4615         double  h[3],s[3],b[3],ba[3];
    4616         double  bed_hydro;
    4617         double  rho_water,rho_ice,density;
    4618         int     isonshelf[3];
    4619         int     i;
    4620         bool    elementonshelf = false;
    4621 
    4622 
    4623         /*Recover info at the vertices: */
    4624         Input* surface_input =inputs->GetInput(SurfaceEnum); _assert_(surface_input);
    4625         Input* bed_input     =inputs->GetInput(BedEnum);     _assert_(bed_input);
    4626         if((surface_input->Enum()!=TriaVertexInputEnum) | (bed_input->Enum()!=TriaVertexInputEnum))_error_(" not supported yet for bed and surface interpolations not P1!");
    4627 
    4628         GetParameterListOnVertices(&h[0],ThicknessEnum);
    4629         GetParameterListOnVertices(&s[0],SurfaceEnum);
    4630         GetParameterListOnVertices(&b[0],BedEnum);
    4631         GetParameterListOnVertices(&ba[0],BathymetryEnum);
    4632         for(i=0;i<3;i++){
    4633                 isonshelf[i]=nodes[i]->IsOnShelf();
    4634                 if((nodes[i]->Sid()+1)==36)printf("MigrateGroundingLine: El %i Node %i shelf status %i\n",this->Id(),nodes[i]->Sid()+1,isonshelf[i]);
    4635         }
    4636 
    4637         /*material parameters: */
    4638         rho_water=matpar->GetRhoWater();
    4639         rho_ice=matpar->GetRhoIce();
    4640         density=rho_ice/rho_water;
    4641 
    4642         /*go through vertices, and update inputs, considering them to be TriaVertex type: */
    4643         for(i=0;i<3;i++){
    4644                 if (isonshelf[i]){
    4645                         /*This node is on the shelf. See if its bed is going under the bathymetry: */
    4646                         if(b[i]<=ba[i]){ //<= because Neff being 0 when b=ba, drag will be 0 anyway.
    4647                                 /*The ice shelf is getting grounded, the thickness is the same, so just update the bed to stick to the bathymetry and elevate the surface accordingly: */
    4648                                 b[i]=ba[i];
    4649                                 s[i]=b[i]+h[i];
    4650                                 if((nodes[i]->Sid()+1)==36)printf("MigrateGroundingLine: El %i Node %i grounding %g %g %g\n",this->Id(),nodes[i]->Sid()+1,b[i],ba[i],s[i]);
    4651                         }
    4652                         else{
    4653                                 /*do nothing, we are still floating.*/
    4654                                 if((nodes[i]->Sid()+1)==36)printf("MigrateGroundingLine: El %i Node %i still floating %g %g %g\n",this->Id(),nodes[i]->Sid()+1,b[i],ba[i],s[i]);
    4655                         }
    4656                 }
    4657                 else{
    4658                         /*This node is on the sheet, near the grounding line. See if wants to unground. To
    4659                          * do so, we compute the hydrostatic bed, and if it is > bathymetry, then we unground: */
    4660                         bed_hydro=-density*h[i];
    4661                         if (bed_hydro>ba[i]){
    4662                                 /*We are now floating, bed and surface are determined from hydrostatic equilibrium: */
    4663                                 s[i]=(1-density)*h[i];
    4664                                 b[i]=-density*h[i];
    4665                                 printf("%i\n",nodes[i]->Sid()+1);
    4666                                 if((nodes[i]->Sid()+1)==36)printf("MigrateGroundingLine: El %i Node %i floating %g %g %g\n",this->Id(),nodes[i]->Sid()+1,b[i],ba[i],s[i]);
    4667                         }
    4668                         else{
    4669                                 /*do nothing, we are still grounded.*/
    4670                                 if((nodes[i]->Sid()+1)==36)printf("MigrateGroundingLine: El %i Node %i still grounded %g %g %g\n",this->Id(),nodes[i]->Sid()+1,b[i],ba[i],s[i]);
    4671                         }
    4672                 }
    4673         }
    4674 
    4675         /*Surface and bed are updated. Update inputs:*/
    4676         surface_input->GetValuesPtr(&values,NULL); for(i=0;i<3;i++)values[i]=s[i];
    4677         bed_input->GetValuesPtr(&values,NULL);     for(i=0;i<3;i++)values[i]=b[i];
     5348        /*Start looping on the number of gaussian points:*/
     5349        gauss=new GaussTria(2);
     5350        for (ig=gauss->begin();ig<gauss->end();ig++){
     5351
     5352                gauss->GaussPoint(ig);
     5353
     5354                GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss);
     5355                /*WARNING: B and Bprime are inverted compared to usual prognostic!!!!*/
     5356                GetBPrognostic(&Bprime[0][0], &xyz_list[0][0], gauss);
     5357                GetBprimePrognostic(&B[0][0], &xyz_list[0][0], gauss);
     5358
     5359                vx_input->GetParameterValue(&vx,gauss);
     5360                vy_input->GetParameterValue(&vy,gauss);
     5361
     5362                DL_scalar=-gauss->weight*Jdettria;
     5363                DL[0][0]=DL_scalar*vx;
     5364                DL[1][1]=DL_scalar*vy;
     5365
     5366                TripleMultiply( &B[0][0],2,numdof,1,
     5367                                        &DL[0][0],2,2,0,
     5368                                        &Bprime[0][0],2,numdof,0,
     5369                                        &Ke->values[0],1);
     5370        }
     5371
     5372        /*Clean up and return*/
     5373        delete gauss;
     5374        return Ke;
     5375}
     5376/*}}}*/
     5377/*FUNCTION Tria::CreatePVectorBalancethickness{{{1*/
     5378ElementVector* Tria::CreatePVectorBalancethickness(void){
     5379
     5380        switch(GetElementType()){
     5381                case P1Enum:
     5382                        return CreatePVectorBalancethickness_CG();
     5383                        break;
     5384                case P1DGEnum:
     5385                        return CreatePVectorBalancethickness_DG();
     5386                default:
     5387                        _error_("Element type %s not supported yet",EnumToStringx(GetElementType()));
     5388        }
     5389}
     5390/*}}}*/
     5391/*FUNCTION Tria::CreatePVectorBalancethickness_CG{{{1*/
     5392ElementVector* Tria::CreatePVectorBalancethickness_CG(void){
     5393
     5394        /*Constants*/
     5395        const int    numdof=NDOF1*NUMVERTICES;
    46785396       
    4679         for(i=0;i<3;i++){
    4680                 isonshelf[i]=nodes[i]->IsOnShelf();
    4681                 if((nodes[i]->Sid()+1)==36)printf("MigrateGroundingLine: El %i Node %i second shelf status %i\n",this->Id(),nodes[i]->Sid()+1,isonshelf[i]);
    4682         }
    4683 }
    4684 /*}}}*/
    4685 /*FUNCTION Tria::MinVel{{{1*/
    4686 void  Tria::MinVel(double* pminvel, bool process_units){
    4687 
    4688         /*Get minimum:*/
    4689         double minvel=this->inputs->Min(VelEnum);
    4690 
    4691         /*process units if requested: */
    4692         if(process_units) minvel=UnitConversion(minvel,IuToExtEnum,VelEnum);
    4693 
    4694         /*Assign output pointers:*/
    4695         *pminvel=minvel;
    4696 }
    4697 /*}}}*/
    4698 /*FUNCTION Tria::MinVx{{{1*/
    4699 void  Tria::MinVx(double* pminvx, bool process_units){
    4700 
    4701         /*Get minimum:*/
    4702         double minvx=this->inputs->Min(VxEnum);
    4703 
    4704         /*process units if requested: */
    4705         if(process_units) minvx=UnitConversion(minvx,IuToExtEnum,VxEnum);
    4706 
    4707         /*Assign output pointers:*/
    4708         *pminvx=minvx;
    4709 }
    4710 /*}}}*/
    4711 /*FUNCTION Tria::MinVy{{{1*/
    4712 void  Tria::MinVy(double* pminvy, bool process_units){
    4713 
    4714         /*Get minimum:*/
    4715         double minvy=this->inputs->Min(VyEnum);
    4716 
    4717         /*process units if requested: */
    4718         if(process_units) minvy=UnitConversion(minvy,IuToExtEnum,VyEnum);
    4719 
    4720         /*Assign output pointers:*/
    4721         *pminvy=minvy;
    4722 }
    4723 /*}}}*/
    4724 /*FUNCTION Tria::MinVz{{{1*/
    4725 void  Tria::MinVz(double* pminvz, bool process_units){
    4726 
    4727         /*Get minimum:*/
    4728         double minvz=this->inputs->Min(VzEnum);
    4729 
    4730         /*process units if requested: */
    4731         if(process_units) minvz=UnitConversion(minvz,IuToExtEnum,VzEnum);
    4732 
    4733         /*Assign output pointers:*/
    4734         *pminvz=minvz;
    4735 }
    4736 /*}}}*/
    4737 /*FUNCTION Tria::MyRank {{{1*/
    4738 int    Tria::MyRank(void){
    4739         extern int my_rank;
    4740         return my_rank;
    4741 }
    4742 /*}}}*/
    4743 /*FUNCTION Tria::NodalValue {{{1*/
    4744 int    Tria::NodalValue(double* pvalue, int index, int natureofdataenum,bool process_units){
    4745 
    4746         int i;
    4747         int found=0;
    4748         double value;
    4749         Input* data=NULL;
    4750         GaussTria *gauss                            = NULL;
    4751 
    4752         /*First, serarch the input: */
    4753         data=inputs->GetInput(natureofdataenum);
    4754 
    4755         /*figure out if we have the vertex id: */
    4756         found=0;
    4757         for(i=0;i<NUMVERTICES;i++){
    4758                 if(index==nodes[i]->GetVertexId()){
    4759                         /*Do we have natureofdataenum in our inputs? :*/
    4760                         if(data){
    4761                                 /*ok, we are good. retrieve value of input at vertex :*/
    4762                                 gauss=new GaussTria(); gauss->GaussVertex(i);
    4763                                 data->GetParameterValue(&value,gauss);
    4764                                 found=1;
    4765                                 break;
    4766                         }
    4767                 }
    4768         }
    4769 
    4770         if(found)*pvalue=value;
    4771         return found;
    4772 }
    4773 /*}}}*/
    4774 /*FUNCTION Tria::PatchFill{{{1*/
    4775 void  Tria::PatchFill(int* prow, Patch* patch){
    4776 
    4777         int i,row;
    4778         int vertices_ids[3];
    4779 
    4780         /*recover pointer: */
    4781         row=*prow;
    4782                
    4783         for(i=0;i<3;i++) vertices_ids[i]=nodes[i]->GetVertexId(); //vertices id start at column 3 of the patch.
    4784 
    4785         for(i=0;i<this->results->Size();i++){
    4786                 ElementResult* elementresult=(ElementResult*)this->results->GetObjectByOffset(i);
    4787 
    4788                 /*For this result,fill the information in the Patch object (element id + vertices ids), and then hand
    4789                  *it to the result object, to fill the rest: */
    4790                 patch->fillelementinfo(row,this->sid+1,vertices_ids,3);
    4791                 elementresult->PatchFill(row,patch);
    4792 
    4793                 /*increment rower: */
    4794                 row++;
    4795         }
    4796 
    4797         /*Assign output pointers:*/
    4798         *prow=row;
    4799 }
    4800 /*}}}*/
    4801 /*FUNCTION Tria::PatchSize{{{1*/
    4802 void  Tria::PatchSize(int* pnumrows, int* pnumvertices,int* pnumnodes){
    4803 
    4804         int     i;
    4805         int     numrows     = 0;
    4806         int     numnodes    = 0;
    4807         int     temp_numnodes    = 0;
    4808 
    4809         /*Go through all the results objects, and update the counters: */
    4810         for (i=0;i<this->results->Size();i++){
    4811                 ElementResult* elementresult=(ElementResult*)this->results->GetObjectByOffset(i);
    4812                 /*first, we have one more result: */
    4813                 numrows++;
    4814                 /*now, how many vertices and how many nodal values for this result? :*/
    4815                 temp_numnodes=elementresult->NumberOfNodalValues(); //ask result object.
    4816                 if(temp_numnodes>numnodes)numnodes=temp_numnodes;
    4817         }
    4818 
    4819         /*Assign output pointers:*/
    4820         *pnumrows=numrows;
    4821         *pnumvertices=NUMVERTICES;
    4822         *pnumnodes=numnodes;
    4823 }
    4824 /*}}}*/
    4825 /*FUNCTION Tria::PotentialSheetUngrounding{{{1*/
    4826 void  Tria::PotentialSheetUngrounding(Vec potential_sheet_ungrounding){
    4827 
    4828 
    4829         double *values         = NULL;
    4830         double  h[3],s[3],b[3],ba[3];
    4831         double  bed_hydro;
    4832         double  rho_water,rho_ice,density;
    4833         int     i;
    4834         bool    elementonshelf = false;
    4835 
    4836         /*Recover info at the vertices: */
    4837         Input* surface_input =inputs->GetInput(SurfaceEnum); _assert_(surface_input);
    4838         Input* bed_input     =inputs->GetInput(BedEnum);     _assert_(bed_input);
    4839         if((surface_input->Enum()!=TriaVertexInputEnum) | (bed_input->Enum()!=TriaVertexInputEnum))_error_(" not supported yet for bed and surface interpolations not P1!");
    4840 
    4841         GetParameterListOnVertices(&h[0],ThicknessEnum);
    4842         GetParameterListOnVertices(&s[0],SurfaceEnum);
    4843         GetParameterListOnVertices(&b[0],BedEnum);
    4844         GetParameterListOnVertices(&ba[0],BathymetryEnum);
    4845 
    4846         /*material parameters: */
    4847         rho_water=matpar->GetRhoWater();
    4848         rho_ice=matpar->GetRhoIce();
    4849         density=rho_ice/rho_water;
    4850 
    4851         /*go through vertices, and figure out which ones are on the ice sheet, and want to unground: */
    4852         for(i=0;i<3;i++){
    4853                 if (!nodes[i]->IsOnShelf()){
    4854                        
    4855                         /*This node is on the sheet, near the grounding line. See if wants to unground. To
    4856                          * do so, we compute the hydrostatic bed, and if it is > bathymetry, then we unground: */
    4857                         bed_hydro=-density*h[i];
    4858                         if (bed_hydro>ba[i]){
    4859                                 /*ok, this node wants to unground. flag it: */
    4860                                 VecSetValue(potential_sheet_ungrounding,nodes[i]->Sid(),1,INSERT_VALUES);
    4861                         }
    4862                 }
    4863         }
    4864 }
    4865 /*}}}*/
    4866 /*FUNCTION Tria::ProcessResultsUnits{{{1*/
    4867 void  Tria::ProcessResultsUnits(void){
    4868 
    4869         int i;
    4870 
    4871         for(i=0;i<this->results->Size();i++){
    4872                 ElementResult* elementresult=(ElementResult*)this->results->GetObjectByOffset(i);
    4873                 elementresult->ProcessUnits(this->parameters);
    4874         }
    4875 }
    4876 /*}}}*/
    4877 /*FUNCTION Tria::RheologyBbarx{{{1*/
    4878 double Tria::RheologyBbarx(void){
    4879 
    4880         return this->matice->GetBbar();
    4881 
    4882 }
    4883 /*}}}*/
    4884 /*FUNCTION Tria::RequestedOutput{{{1*/
    4885 void Tria::RequestedOutput(int output_enum,int step,double time){
    4886 
    4887         if(IsInput(output_enum)){
    4888                 /*just transfer this input to results, and we are done: */
    4889                 InputToResult(output_enum,step,time);
    4890         }
    4891         else{
    4892                 /*this input does not exist, compute it, and then transfer to results: */
    4893                 switch(output_enum){
    4894                         default:
    4895                                 /*do nothing, no need to derail the computation because one of the outputs requested cannot be found: */
    4896                                 break;
    4897                 }
    4898         }
    4899 
    4900 }
    4901 /*}}}*/
    4902 /*FUNCTION Tria::SetClone {{{1*/
    4903 void  Tria::SetClone(int* minranks){
    4904 
    4905         _error_("not implemented yet");
    4906 }
    4907 /*}}}1*/
    4908 /*FUNCTION Tria::SetCurrentConfiguration {{{1*/
    4909 void  Tria::SetCurrentConfiguration(Elements* elementsin, Loads* loadsin, DataSet* nodesin, Materials* materialsin, Parameters* parametersin){
     5397        /*Intermediaries */
     5398        int        i,j,ig;
     5399        double     xyz_list[NUMVERTICES][3];
     5400        double     dhdt_g,basal_melting_g,surface_mass_balance_g,Jdettria;
     5401        double     L[NUMVERTICES];
     5402        GaussTria* gauss=NULL;
     5403
     5404        /*Initialize Element vector*/
     5405        ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters);
     5406
     5407        /*Retrieve all inputs and parameters*/
     5408        GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
     5409        Input* surface_mass_balance_input=inputs->GetInput(SurfaceforcingsMassBalanceEnum); _assert_(surface_mass_balance_input);
     5410        Input* basal_melting_input=inputs->GetInput(BasalforcingsMeltingRateEnum);          _assert_(basal_melting_input);
     5411        Input* dhdt_input=inputs->GetInput(BalancethicknessThickeningRateEnum);             _assert_(dhdt_input);
    49105412       
    4911         /*go into parameters and get the analysis_counter: */
    4912         int analysis_counter;
    4913         parametersin->FindParam(&analysis_counter,AnalysisCounterEnum);
    4914 
    4915         /*Get Element type*/
    4916         this->element_type=this->element_type_list[analysis_counter];
    4917 
    4918         /*Pick up nodes*/
    4919         if(this->hnodes[analysis_counter]) this->nodes=(Node**)this->hnodes[analysis_counter]->deliverp();
    4920         else this->nodes=NULL;
    4921 
    4922 }
    4923 /*}}}*/
    4924 /*FUNCTION Tria::ShelfSync{{{1*/
    4925 void  Tria::ShelfSync(void){
    4926 
    4927 
    4928         double *values         = NULL;
    4929         double  h[3],s[3],b[3],ba[3];
    4930         double  bed_hydro;
    4931         double  rho_water,rho_ice,density;
    4932         int     i;
    4933         bool    elementonshelf = false;
    4934 
    4935         /*melting rate at the grounding line: */
    4936         double  yts;
    4937         int     swap;
    4938         double  gl_melting_rate;
    4939 
    4940         /*recover parameters: */
    4941         parameters->FindParam(&yts,ConstantsYtsEnum);
    4942         parameters->FindParam(&gl_melting_rate,GroundinglineMeltingRateEnum);
    4943 
    4944         /*Recover info at the vertices: */
    4945         Input* surface_input =inputs->GetInput(SurfaceEnum); _assert_(surface_input);
    4946         Input* bed_input     =inputs->GetInput(BedEnum);     _assert_(bed_input);
    4947         if((surface_input->Enum()!=TriaVertexInputEnum) | (bed_input->Enum()!=TriaVertexInputEnum))_error_(" not supported yet for bed and surface interpolations not P1!");
    4948 
    4949         GetParameterListOnVertices(&h[0],ThicknessEnum);
    4950         GetParameterListOnVertices(&s[0],SurfaceEnum);
    4951         GetParameterListOnVertices(&b[0],BedEnum);
    4952         GetParameterListOnVertices(&ba[0],BathymetryEnum);
    4953 
    4954         /*material parameters: */
    4955         rho_water=matpar->GetRhoWater();
    4956         rho_ice=matpar->GetRhoIce();
    4957         density=rho_ice/rho_water;
    4958 
    4959         /*go through vertices, and update inputs, considering them to be TriaVertex type: */
    4960         for(i=0;i<3;i++){
    4961                 if(b[i]==ba[i]){
    4962                                
    4963                         nodes[i]->inputs->AddInput(new BoolInput(MaskVertexonfloatingiceEnum,false));
    4964                         nodes[i]->inputs->AddInput(new BoolInput(MaskVertexongroundediceEnum,true));
    4965                 }
    4966                 else{
    4967                         nodes[i]->inputs->AddInput(new BoolInput(MaskVertexonfloatingiceEnum,true));
    4968                         nodes[i]->inputs->AddInput(new BoolInput(MaskVertexongroundediceEnum,false));
    4969 
    4970                 }
    4971         }
    4972 
    4973         /*Now, update  shelf status of element. An element can only be on shelf if all its nodes are on shelf: */
    4974         swap=0;
    4975         elementonshelf=false;
    4976         for(i=0;i<3;i++){
    4977                 if(nodes[i]->IsOnShelf()){
    4978                         elementonshelf=true;
    4979                         break;
    4980                 }
    4981         }
    4982         if(!this->IsOnShelf() && elementonshelf==true)swap=1;
    4983     this->inputs->AddInput(new BoolInput(MaskElementonfloatingiceEnum,elementonshelf));
    4984        
    4985     /*If this element just  became ungrounded, set its basal melting rate at 50 m/yr:*/
    4986         if(swap){
    4987                 Input* basal_melting_rate_input     =inputs->GetInput(BasalforcingsMeltingRateEnum);     _assert_(basal_melting_rate_input);
    4988                 basal_melting_rate_input->GetValuesPtr(&values,NULL); for(i=0;i<3;i++)values[i]=gl_melting_rate/yts;
    4989         }
    4990 
    4991 
    4992 }
    4993 /*}}}*/
    4994 /*FUNCTION Tria::SoftMigration{{{1*/
    4995 void  Tria::SoftMigration(double* sheet_ungrounding){
    4996 
    4997 
    4998         double *values         = NULL;
    4999         double  h[3],s[3],b[3],ba[3];
    5000         double  bed_hydro;
    5001         double  rho_water,rho_ice,density;
    5002         int     i;
    5003         bool    elementonshelf = false;
    5004 
    5005         /*Recover info at the vertices: */
    5006         Input* surface_input =inputs->GetInput(SurfaceEnum); _assert_(surface_input);
    5007         Input* bed_input     =inputs->GetInput(BedEnum);     _assert_(bed_input);
    5008         if((surface_input->Enum()!=TriaVertexInputEnum) | (bed_input->Enum()!=TriaVertexInputEnum))_error_(" not supported yet for bed and surface interpolations not P1!");
    5009 
    5010         GetParameterListOnVertices(&h[0],ThicknessEnum);
    5011         GetParameterListOnVertices(&s[0],SurfaceEnum);
    5012         GetParameterListOnVertices(&b[0],BedEnum);
    5013         GetParameterListOnVertices(&ba[0],BathymetryEnum);
    5014 
    5015         /*material parameters: */
    5016         rho_water=matpar->GetRhoWater();
    5017         rho_ice=matpar->GetRhoIce();
    5018         density=rho_ice/rho_water;
    5019        
    5020         /*go through vertices, and update inputs, considering them to be TriaVertex type: */
    5021         for(i=0;i<3;i++){
    5022                 if (nodes[i]->IsOnShelf()){
    5023                         /*This node is on the shelf. See if its bed is going under the bathymetry: */
    5024                         if(b[i]<=ba[i]){ //<= because Neff being 0 when b=ba, drag will be 0 anyway.
    5025                                 /*The ice shelf is getting grounded, the thickness is the same, so just update the bed to stick to the bathymetry and elevate the surface accordingly: */
    5026                                 b[i]=ba[i];
    5027                                 s[i]=b[i]+h[i];
    5028                         }
    5029                         else{
    5030                                 /*do nothing, we are still floating.*/
    5031                         }
    5032                 }
    5033                 else{
    5034                         /*This node is on the sheet, near the grounding line. See if wants to unground. To
    5035                          * do so, we compute the hydrostatic bed, and if it is > bathymetry, then we unground: */
    5036                         bed_hydro=-density*h[i];
    5037                         if (bed_hydro>ba[i]){
    5038 
    5039                                 /*Now, are we connected to the grounding line, if so, go forward, otherwise, bail out: */
    5040                                 if(sheet_ungrounding[nodes[i]->Sid()]){
    5041                                         /*We are now floating, bed and surface are determined from hydrostatic equilibrium: */
    5042                                         s[i]=(1-density)*h[i];
    5043                                         b[i]=-density*h[i];
    5044                                 }
    5045                         }
    5046                         else{
    5047                                 /*do nothing, we are still grounded.*/
    5048                         }
    5049                 }
    5050         }
    5051 
    5052         /*Surface and bed are updated. Update inputs:*/   
    5053         surface_input->GetValuesPtr(&values,NULL); for(i=0;i<3;i++)values[i]=s[i];
    5054         bed_input->GetValuesPtr(&values,NULL);     for(i=0;i<3;i++)values[i]=b[i];
    5055 
    5056         }
    5057 /*}}}*/
    5058 /*FUNCTION Tria::SurfaceArea {{{1*/
    5059 double Tria::SurfaceArea(void){
    5060 
    5061         int    i;
    5062         double S;
    5063         double normal[3];
    5064         double v13[3],v23[3];
    5065         double xyz_list[NUMVERTICES][3];
    5066 
    5067         /*If on water, return 0: */
    5068         if(IsOnWater())return 0;
    5069 
     5413        /* Start  looping on the number of gaussian points: */
     5414        gauss=new GaussTria(2);
     5415        for(ig=gauss->begin();ig<gauss->end();ig++){
     5416
     5417                gauss->GaussPoint(ig);
     5418
     5419                surface_mass_balance_input->GetParameterValue(&surface_mass_balance_g,gauss);
     5420                basal_melting_input->GetParameterValue(&basal_melting_g,gauss);
     5421                dhdt_input->GetParameterValue(&dhdt_g,gauss);
     5422
     5423                GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss);
     5424                GetL(&L[0], &xyz_list[0][0], gauss,NDOF1);
     5425
     5426                for(i=0;i<numdof;i++) pe->values[i]+=Jdettria*gauss->weight*(surface_mass_balance_g-basal_melting_g-dhdt_g)*L[i];
     5427        }
     5428
     5429        /*Clean up and return*/
     5430        delete gauss;
     5431        return pe;
     5432}
     5433/*}}}*/
     5434/*FUNCTION Tria::CreatePVectorBalancethickness_DG {{{1*/
     5435ElementVector* Tria::CreatePVectorBalancethickness_DG(void){
     5436
     5437        /*Constants*/
     5438        const int    numdof=NDOF1*NUMVERTICES;
     5439
     5440        /*Intermediaries */
     5441        int        i,j,ig;
     5442        double     xyz_list[NUMVERTICES][3];
     5443        double     basal_melting_g,surface_mass_balance_g,dhdt_g,Jdettria;
     5444        double     L[NUMVERTICES];
     5445        GaussTria* gauss=NULL;
     5446
     5447        /*Initialize Element vector*/
     5448        ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters);
     5449
     5450        /*Retrieve all inputs and parameters*/
    50705451        GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
    5071 
    5072         for (i=0;i<3;i++){
    5073                 v13[i]=xyz_list[0][i]-xyz_list[2][i];
    5074                 v23[i]=xyz_list[1][i]-xyz_list[2][i];
    5075         }
    5076 
    5077         normal[0]=v13[1]*v23[2]-v13[2]*v23[1];
    5078         normal[1]=v13[2]*v23[0]-v13[0]*v23[2];
    5079         normal[2]=v13[0]*v23[1]-v13[1]*v23[0];
    5080 
    5081         S = 0.5 * sqrt(pow(normal[0],(double)2)+pow(normal[1],(double)2)+pow(normal[2],(double)2));
    5082 
    5083         /*Return: */
    5084         return S;
    5085 }
    5086 /*}}}*/
    5087 /*FUNCTION Tria::SurfaceNormal{{{1*/
    5088 void Tria::SurfaceNormal(double* surface_normal, double xyz_list[3][3]){
    5089 
    5090         int i;
    5091         double v13[3],v23[3];
    5092         double normal[3];
    5093         double normal_norm;
    5094 
    5095         for (i=0;i<3;i++){
    5096                 v13[i]=xyz_list[0][i]-xyz_list[2][i];
    5097                 v23[i]=xyz_list[1][i]-xyz_list[2][i];
    5098         }
    5099 
    5100         normal[0]=v13[1]*v23[2]-v13[2]*v23[1];
    5101         normal[1]=v13[2]*v23[0]-v13[0]*v23[2];
    5102         normal[2]=v13[0]*v23[1]-v13[1]*v23[0];
    5103 
    5104         normal_norm=sqrt( pow(normal[0],(double)2)+pow(normal[1],(double)2)+pow(normal[2],(double)2) );
    5105 
    5106         *(surface_normal)=normal[0]/normal_norm;
    5107         *(surface_normal+1)=normal[1]/normal_norm;
    5108         *(surface_normal+2)=normal[2]/normal_norm;
    5109 }
    5110 /*}}}*/
    5111 /*FUNCTION Tria::TimeAdapt{{{1*/
    5112 double  Tria::TimeAdapt(void){
    5113 
    5114         /*intermediary: */
    5115         int    i;
    5116         double C,dt;
    5117         double dx,dy;
    5118         double maxx,minx;
    5119         double maxy,miny;
    5120         double maxabsvx,maxabsvy;
    5121         double xyz_list[NUMVERTICES][3];
    5122 
    5123         /*get CFL coefficient:*/
    5124         this->parameters->FindParam(&C,TimesteppingCflCoefficientEnum);
    5125 
    5126         /*Get for Vx and Vy, the max of abs value: */
    5127         this->MaxAbsVx(&maxabsvx,false);
    5128         this->MaxAbsVy(&maxabsvy,false);
    5129 
    5130         /* Get node coordinates and dof list: */
    5131         GetVerticesCoordinates(&xyz_list[0][0], this->nodes, NUMVERTICES);
    5132 
    5133         minx=xyz_list[0][0];
    5134         maxx=xyz_list[0][0];
    5135         miny=xyz_list[0][1];
    5136         maxy=xyz_list[0][1];
    5137 
    5138         for(i=1;i<NUMVERTICES;i++){
    5139                 if (xyz_list[i][0]<minx)minx=xyz_list[i][0];
    5140                 if (xyz_list[i][0]>maxx)maxx=xyz_list[i][0];
    5141                 if (xyz_list[i][1]<miny)miny=xyz_list[i][1];
    5142                 if (xyz_list[i][1]>maxy)maxy=xyz_list[i][1];
    5143         }
    5144         dx=maxx-minx;
    5145         dy=maxy-miny;
    5146 
    5147         /*CFL criterion: */
    5148         dt=C/(maxabsvy/dx+maxabsvy/dy);
    5149 
    5150         return dt;
    5151 }
    5152 /*}}}*/
    5153 /*FUNCTION Tria::Update(int index, IoModel* iomodel,int analysis_counter,int analysis_type){{{1*/
    5154 void Tria::Update(int index, IoModel* iomodel,int analysis_counter,int analysis_type){ //i is the element index
    5155 
    5156         /*Intermediaries*/
    5157         int    i,j;
    5158         int    tria_node_ids[3];
    5159         int    tria_vertex_ids[3];
    5160         int    tria_type;
    5161         double nodeinputs[3];
    5162         double yts;
    5163         int    progstabilization,balancestabilization;
    5164         bool   dakota_analysis;
    5165 
    5166         /*Checks if debuging*/
    5167         /*{{{2*/
    5168         _assert_(iomodel->Data(MeshElementsEnum));
    5169         /*}}}*/
    5170 
    5171         /*Fetch parameters: */
    5172         iomodel->Constant(&yts,ConstantsYtsEnum);
    5173         iomodel->Constant(&progstabilization,PrognosticStabilizationEnum);
    5174         iomodel->Constant(&balancestabilization,BalancethicknessStabilizationEnum);
    5175         iomodel->Constant(&dakota_analysis,QmuIsdakotaEnum);
    5176 
    5177         /*Recover element type*/
    5178         if ((analysis_type==PrognosticAnalysisEnum && progstabilization==3) || (analysis_type==BalancethicknessAnalysisEnum && balancestabilization==3)){
    5179                 /*P1 Discontinuous Galerkin*/
    5180                 tria_type=P1DGEnum;
    5181         }
    5182         else{
    5183                 /*P1 Continuous Galerkin*/
    5184                 tria_type=P1Enum;
    5185         }
    5186         this->SetElementType(tria_type,analysis_counter);
    5187 
    5188         /*Recover vertices ids needed to initialize inputs*/
    5189         for(i=0;i<3;i++){
    5190                 tria_vertex_ids[i]=(int)iomodel->Data(MeshElementsEnum)[3*index+i]; //ids for vertices are in the elements array from Matlab
    5191         }
    5192 
    5193         /*Recover nodes ids needed to initialize the node hook.*/
    5194         if (tria_type==P1DGEnum){
    5195                 /*Discontinuous Galerkin*/
    5196                 tria_node_ids[0]=iomodel->nodecounter+3*index+1;
    5197                 tria_node_ids[1]=iomodel->nodecounter+3*index+2;
    5198                 tria_node_ids[2]=iomodel->nodecounter+3*index+3;
    5199         }
    5200         else{
    5201                 /*Continuous Galerkin*/
    5202                 for(i=0;i<3;i++){
    5203                         tria_node_ids[i]=iomodel->nodecounter+(int)*(iomodel->Data(MeshElementsEnum)+3*index+i); //ids for vertices are in the elements array from Matlab
    5204                 }
    5205         }
    5206 
    5207         /*hooks: */
    5208         this->SetHookNodes(tria_node_ids,analysis_counter); this->nodes=NULL; //set hook to nodes, for this analysis type
    5209 
    5210         /*Fill with IoModel*/
    5211         this->InputUpdateFromIoModel(index,iomodel);
    5212 
    5213         /*Defaults if not provided in iomodel*/
    5214         switch(analysis_type){
    5215 
    5216                 case DiagnosticHorizAnalysisEnum:
    5217 
    5218                         /*default vx,vy and vz: either observation or 0 */
    5219                         if(!iomodel->Data(VxEnum)){
    5220                                 if (iomodel->Data(InversionVxObsEnum)) for(i=0;i<3;i++)nodeinputs[i]=iomodel->Data(InversionVxObsEnum)[tria_vertex_ids[i]-1]/yts;
    5221                                 else                 for(i=0;i<3;i++)nodeinputs[i]=0;
    5222                                 this->inputs->AddInput(new TriaVertexInput(VxEnum,nodeinputs));
    5223                                 this->inputs->AddInput(new TriaVertexInput(VxPicardEnum,nodeinputs));
    5224                                 if(dakota_analysis) this->inputs->AddInput(new TriaVertexInput(QmuVxEnum,nodeinputs));
    5225                         }
    5226                         if(!iomodel->Data(VyEnum)){
    5227                                 if (iomodel->Data(InversionVyObsEnum)) for(i=0;i<3;i++)nodeinputs[i]=iomodel->Data(InversionVyObsEnum)[tria_vertex_ids[i]-1]/yts;
    5228                                 else                 for(i=0;i<3;i++)nodeinputs[i]=0;
    5229                                 this->inputs->AddInput(new TriaVertexInput(VyEnum,nodeinputs));
    5230                                 this->inputs->AddInput(new TriaVertexInput(VyPicardEnum,nodeinputs));
    5231                                 if(dakota_analysis) this->inputs->AddInput(new TriaVertexInput(QmuVyEnum,nodeinputs));
    5232                         }
    5233                         if(!iomodel->Data(VzEnum)){
    5234                                 if (iomodel->Data(InversionVzObsEnum)) for(i=0;i<3;i++)nodeinputs[i]=iomodel->Data(InversionVzObsEnum)[tria_vertex_ids[i]-1]/yts;
    5235                                 else                 for(i=0;i<3;i++)nodeinputs[i]=0;
    5236                                 this->inputs->AddInput(new TriaVertexInput(VzEnum,nodeinputs));
    5237                                 this->inputs->AddInput(new TriaVertexInput(VzPicardEnum,nodeinputs));
    5238                                 if(dakota_analysis) this->inputs->AddInput(new TriaVertexInput(QmuVzEnum,nodeinputs));
    5239                         }
    5240                         if(!iomodel->Data(PressureEnum)){
    5241                                 for(i=0;i<3;i++)nodeinputs[i]=0;
    5242                                 if(dakota_analysis){
    5243                                         this->inputs->AddInput(new TriaVertexInput(PressureEnum,nodeinputs));
    5244                                         this->inputs->AddInput(new TriaVertexInput(QmuPressureEnum,nodeinputs));
    5245                                 }
    5246                         }
    5247                         break;
    5248 
    5249                 default:
    5250                         /*No update for other solution types*/
    5251                         break;
    5252 
    5253         }
    5254 
    5255         //this->parameters: we still can't point to it, it may not even exist. Configure will handle this.
    5256         this->parameters=NULL;
    5257 }
    5258 /*}}}*/
    5259 /*FUNCTION Tria::UpdateShelfStatus{{{1*/
    5260 int  Tria::UpdateShelfStatus(Vec new_shelf_nodes){
    5261 
    5262         int     i;
    5263 
    5264         double  h[3];
    5265         double  s[3];
    5266         double  b[3];
    5267         double  ba[3];
    5268         Input  *surface_input  = NULL;
    5269         Input  *bed_input      = NULL;
    5270         double  rho_water;
    5271         double  rho_ice;
    5272         double  density;
    5273         bool    elementonshelf = false;
    5274         int     flipped=0;
    5275         int     shelfstatus[3];
    5276 
    5277 
    5278         /*Recover info at the vertices: */
    5279         surface_input   =inputs->GetInput(SurfaceEnum);   _assert_(surface_input);
    5280         bed_input   =inputs->GetInput(BedEnum);   _assert_(bed_input);
    5281         if((surface_input->Enum()!=TriaVertexInputEnum) | (bed_input->Enum()!=TriaVertexInputEnum))_error_(" not supported yet for bed and surface interpolations not P1!");
    5282 
    5283         GetParameterListOnVertices(&h[0],ThicknessEnum);
    5284         GetParameterListOnVertices(&s[0],SurfaceEnum);
    5285         GetParameterListOnVertices(&b[0],BedEnum);
    5286         GetParameterListOnVertices(&ba[0],BathymetryEnum);
    5287 
    5288         /*material parameters: */
    5289         rho_water=matpar->GetRhoWater();
    5290         rho_ice=matpar->GetRhoIce();
    5291         density=rho_ice/rho_water;
    5292 
    5293         /*Initialize current status of nodes: */
    5294         for(i=0;i<3;i++){
    5295                 shelfstatus[i]=nodes[i]->IsOnShelf();
    5296                 if((nodes[i]->Sid()+1)==36) printf("UpdateShelfStatus: El %i Node %i shelf status %i\n",this->Id(),nodes[i]->Sid()+1,shelfstatus[i]);
    5297         }
    5298        
    5299         /*go through vertices, and figure out if they are grounded or not, then update their status: */
    5300         flipped=0;
    5301         for(i=0;i<3;i++){
    5302                 if(b[i]<=ba[i]){ //the = will lead to oscillations.
    5303                         nodes[i]->inputs->AddInput(new BoolInput(MaskVertexonfloatingiceEnum,false));
    5304                         nodes[i]->inputs->AddInput(new BoolInput(MaskVertexongroundediceEnum,true));
    5305                         if(shelfstatus[i]){
    5306                                 flipped++;
    5307                                 if((nodes[i]->Sid()+1)==36)printf("UpdateShelfStatus: El %i Node %i grounding %g %g %g\n",this->Id(),nodes[i]->Sid()+1,b[i],ba[i],s[i]);
    5308                         }
    5309                         VecSetValue(new_shelf_nodes,nodes[i]->Sid(),0,INSERT_VALUES);
    5310                 }
    5311                 else{
    5312                         nodes[i]->inputs->AddInput(new BoolInput(MaskVertexonfloatingiceEnum,true));
    5313                         nodes[i]->inputs->AddInput(new BoolInput(MaskVertexongroundediceEnum,false));
    5314                         if(!shelfstatus[i]){
    5315                                 flipped++;
    5316                                 if((nodes[i]->Sid()+1)==36)printf("UpdateShelfStatus: El %i Node %i floating %g %g %g\n",this->Id(),nodes[i]->Sid()+1,b[i],ba[i],s[i]);
    5317                         }
    5318                         VecSetValue(new_shelf_nodes,nodes[i]->Sid(),1,INSERT_VALUES);
    5319                 }
    5320         }
    5321 
    5322         /*Now, update  shelf status of element. An element can only be on shelf if all its nodes are on shelf: */
    5323         elementonshelf=false;
    5324         for(i=0;i<3;i++){
    5325                 if(nodes[i]->IsOnShelf()){
    5326                         elementonshelf=true;
    5327                         break;
    5328                 }
    5329         }
    5330     this->inputs->AddInput(new BoolInput(MaskElementonfloatingiceEnum,elementonshelf));
    5331 
    5332          return flipped;
    5333 }
    5334 /*}}}*/
    5335 /*FUNCTION Tria::UpdateShelfFlags{{{1*/
    5336 void Tria::UpdateShelfFlags(double* new_shelf_nodes){
    5337 
    5338         /*go through vertices, and update the status of MaskVertexonfloatingiceEnum and MaskVertexongroundediceEnum flags: */
    5339         bool flag;
    5340         int  i;
    5341         double  h[3];
    5342         double  s[3];
    5343         double  b[3];
    5344         double  ba[3];
    5345 
    5346         GetParameterListOnVertices(&h[0],ThicknessEnum);
    5347         GetParameterListOnVertices(&s[0],SurfaceEnum);
    5348         GetParameterListOnVertices(&b[0],BedEnum);
    5349         GetParameterListOnVertices(&ba[0],BathymetryEnum);
    5350 
    5351         for(i=0;i<3;i++){
    5352                 flag=(bool)new_shelf_nodes[nodes[i]->Sid()];
    5353                 nodes[i]->inputs->AddInput(new BoolInput(MaskVertexonfloatingiceEnum,flag));
    5354                 nodes[i]->inputs->AddInput(new BoolInput(MaskVertexongroundediceEnum,!flag));
    5355         }
    5356 }
    5357 /*}}}*/
    5358 /*FUNCTION Tria::UpdatePotentialSheetUngrounding{{{1*/
    5359 int Tria::UpdatePotentialSheetUngrounding(double* potential_sheet_ungrounding,Vec vec_nodes_on_iceshelf,double* nodes_on_iceshelf){
    5360 
    5361         /*intermediary: */
    5362         int i;
    5363         int nflipped=0;
    5364 
    5365         /*Ok, go through our 3 nodes, and whoever is on the potential_sheet_ungrounding, ends up in nodes_on_iceshelf: */
    5366         for(i=0;i<3;i++){
    5367                 if (potential_sheet_ungrounding[nodes[i]->Sid()]){
    5368                         VecSetValue(vec_nodes_on_iceshelf,nodes[i]->Sid(),1,INSERT_VALUES);
    5369                
    5370                         /*Figure out if we flipped: */
    5371                         if (potential_sheet_ungrounding[nodes[i]->Sid()] != nodes_on_iceshelf[nodes[i]->Sid()])nflipped++;
    5372                 }
    5373         }
    5374         return nflipped;
    5375 }
    5376 /*}}}*/
     5452        Input* surface_mass_balance_input=inputs->GetInput(SurfaceforcingsMassBalanceEnum); _assert_(surface_mass_balance_input);
     5453        Input* basal_melting_input=inputs->GetInput(BasalforcingsMeltingRateEnum);          _assert_(basal_melting_input);
     5454        Input* dhdt_input=inputs->GetInput(BalancethicknessThickeningRateEnum);                                       _assert_(dhdt_input);
     5455
     5456        /* Start  looping on the number of gaussian points: */
     5457        gauss=new GaussTria(2);
     5458        for(ig=gauss->begin();ig<gauss->end();ig++){
     5459
     5460                gauss->GaussPoint(ig);
     5461
     5462                surface_mass_balance_input->GetParameterValue(&surface_mass_balance_g,gauss);
     5463                basal_melting_input->GetParameterValue(&basal_melting_g,gauss);
     5464                dhdt_input->GetParameterValue(&dhdt_g,gauss);
     5465
     5466                GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss);
     5467                GetL(&L[0], &xyz_list[0][0], gauss,NDOF1);
     5468
     5469                for(i=0;i<numdof;i++) pe->values[i]+=Jdettria*gauss->weight*(surface_mass_balance_g-basal_melting_g-dhdt_g)*L[i];
     5470        }
     5471
     5472        /*Clean up and return*/
     5473        delete gauss;
     5474        return pe;
     5475}
     5476/*}}}*/
     5477#endif
     5478
  • issm/trunk/src/c/objects/Elements/Tria.h

    r9761 r9775  
    8989                void   GetSolutionFromInputs(Vec solution);
    9090                void   GetVectorFromInputs(Vec vector,int NameEnum);
    91                 #ifdef _HAVE_CONTROL_
    92                 double DragCoefficientAbsGradient(bool process_units,int weight_index);
    93                 void   Gradj(Vec gradient,int control_type);
    94                 void   GradjBGradient(Vec gradient,int weight_index);
    95                 void   GradjBMacAyeal(Vec gradient);
    96                 void   GradjDragMacAyeal(Vec gradient);
    97                 void   GradjDragStokes(Vec gradient);
    98                 void   GradjDragGradient(Vec gradient,int weight_index);
    99                 void   GradjDhDtBalancedthickness(Vec gradient);
    100                 void   GradjVxBalancedthickness(Vec gradient);
    101                 void   GradjVyBalancedthickness(Vec gradient);
    102                 void   ControlInputGetGradient(Vec gradient,int enum_type);
    103                 void   ControlInputScaleGradient(int enum_type,double scale);
    104                 void   ControlInputSetGradient(double* gradient,int enum_type);
    105                 double RheologyBbarAbsGradient(bool process_units,int weight_index);
    106                 double ThicknessAbsMisfit(     bool process_units,int weight_index);
    107                 double SurfaceAbsVelMisfit(    bool process_units,int weight_index);
    108                 double ThicknessAbsGradient(bool process_units,int weight_index);
    109                 double SurfaceRelVelMisfit(    bool process_units,int weight_index);
    110                 double SurfaceLogVelMisfit(    bool process_units,int weight_index);
    111                 double SurfaceLogVxVyMisfit(   bool process_units,int weight_index);
    112                 double SurfaceAverageVelMisfit(bool process_units,int weight_index);
    113                 void   InputControlUpdate(double scalar,bool save_parameter);
    114                 #endif
    115 
     91               
    11692                void   InputArtificialNoise(int enum_type,double min, double max);
    11793                bool   InputConvergence(double* eps, int* enums,int num_enums,int* criterionenums,double* criterionvalues,int num_criterionenums);
     
    12197                void   InputDuplicate(int original_enum,int new_enum);
    12298                void   InputScale(int enum_type,double scale_factor);
    123                                 void   InputToResult(int enum_type,int step,double time);
     99                void   InputToResult(int enum_type,int step,double time);
    124100                void   DeleteResults(void);
    125101                void   MaterialUpdateFromTemperature(void){_error_("not implemented yet");};
     
    154130                double RheologyBbarx(void);
    155131                int    NodalValue(double* pvalue, int index, int natureofdataenum,bool process_units);
     132
     133
     134                #ifdef _HAVE_CONTROL_
     135                double DragCoefficientAbsGradient(bool process_units,int weight_index);
     136                void   Gradj(Vec gradient,int control_type);
     137                void   GradjBGradient(Vec gradient,int weight_index);
     138                void   GradjBMacAyeal(Vec gradient);
     139                void   GradjDragMacAyeal(Vec gradient);
     140                void   GradjDragStokes(Vec gradient);
     141                void   GradjDragGradient(Vec gradient,int weight_index);
     142                void   GradjDhDtBalancedthickness(Vec gradient);
     143                void   GradjVxBalancedthickness(Vec gradient);
     144                void   GradjVyBalancedthickness(Vec gradient);
     145                void   ControlInputGetGradient(Vec gradient,int enum_type);
     146                void   ControlInputScaleGradient(int enum_type,double scale);
     147                void   ControlInputSetGradient(double* gradient,int enum_type);
     148                double RheologyBbarAbsGradient(bool process_units,int weight_index);
     149                double ThicknessAbsMisfit(     bool process_units,int weight_index);
     150                double SurfaceAbsVelMisfit(    bool process_units,int weight_index);
     151                double ThicknessAbsGradient(bool process_units,int weight_index);
     152                double SurfaceRelVelMisfit(    bool process_units,int weight_index);
     153                double SurfaceLogVelMisfit(    bool process_units,int weight_index);
     154                double SurfaceLogVxVyMisfit(   bool process_units,int weight_index);
     155                double SurfaceAverageVelMisfit(bool process_units,int weight_index);
     156                void   InputControlUpdate(double scalar,bool save_parameter);
     157                #endif
     158
    156159                /*}}}*/
    157160                /*Tria specific routines:{{{1*/
    158                 ElementMatrix* CreateKMatrixAdjointBalancethickness(void);
    159161                ElementMatrix* CreateKMatrixBalancethickness(void);
    160162                ElementMatrix* CreateKMatrixBalancethickness_DG(void);
    161163                ElementMatrix* CreateKMatrixBalancethickness_CG(void);
    162                 ElementMatrix* CreateKMatrixDiagnosticMacAyeal(void);
    163                 ElementMatrix* CreateKMatrixDiagnosticMacAyealViscous(void);
    164                 ElementMatrix* CreateKMatrixDiagnosticMacAyealFriction(void);
    165                 ElementMatrix* CreateKMatrixDiagnosticHutter(void);
    166164                ElementMatrix* CreateKMatrixMelting(void);
    167                 ElementMatrix* CreateKMatrixHydrology(void);
    168165                ElementMatrix* CreateKMatrixPrognostic(void);
    169166                ElementMatrix* CreateKMatrixPrognostic_CG(void);
     
    173170                ElementVector* CreatePVectorBalancethickness_DG(void);
    174171                ElementVector* CreatePVectorBalancethickness_CG(void);
    175                 ElementVector* CreatePVectorDiagnosticMacAyeal(void);
    176                 ElementVector* CreatePVectorAdjointHoriz(void);
    177                 ElementVector* CreatePVectorAdjointStokes(void);
    178                 ElementVector* CreatePVectorAdjointBalancethickness(void);
    179                 ElementVector* CreatePVectorDiagnosticHutter(void);
    180                 ElementVector* CreatePVectorHydrology(void);
    181172                ElementVector* CreatePVectorPrognostic(void);
    182173                ElementVector* CreatePVectorPrognostic_CG(void);
    183174                ElementVector* CreatePVectorPrognostic_DG(void);
    184175                ElementVector* CreatePVectorSlope(void);
    185                 double  GetArea(void);
    186                 int     GetElementType(void);
    187                 void      GetDofList(int** pdoflist,int approximation_enum,int setenum);
    188                 void    CreateHydrologyWaterVelocityInput(void);
    189                 void      GetDofList1(int* doflist);
    190                 void    GetSidList(int* sidlist);
    191                 void    GetParameterListOnVertices(double* pvalue,int enumtype);
    192                 void    GetParameterListOnVertices(double* pvalue,int enumtype,double defaultvalue);
    193                 void    GetParameterListOnVertices(double* pvalue,int enumtype,double defaultvalue,int index); //TO BE REMOVED
    194                 void    GetParameterValue(double* pvalue,Node* node,int enumtype);
     176                double         GetArea(void);
     177                int            GetElementType(void);
     178                void           GetDofList(int** pdoflist,int approximation_enum,int setenum);
     179                void           GetDofList1(int* doflist);
     180                void           GetSidList(int* sidlist);
     181                void           GetParameterListOnVertices(double* pvalue,int enumtype);
     182                void           GetParameterListOnVertices(double* pvalue,int enumtype,double defaultvalue);
     183                void           GetParameterListOnVertices(double* pvalue,int enumtype,double defaultvalue,int index); //TO BE REMOVED
     184                void           GetParameterValue(double* pvalue,Node* node,int enumtype);
     185                void           GetStrainRate2d(double* epsilon,double* xyz_list, GaussTria* gauss, Input* vx_input, Input* vy_input);
     186                void           InputUpdateFromSolutionOneDof(double* solution,int enum_type);
     187                void           InputUpdateFromSolutionPrognostic(double* solution);
     188                bool           IsInput(int name);
     189                void           SetClone(int* minranks);
     190                void           SurfaceNormal(double* surface_normal, double xyz_list[3][3]);
     191
     192               
     193                #ifdef _HAVE_DIAGNOSTIC_
     194                ElementMatrix* CreateKMatrixDiagnosticMacAyeal(void);
     195                ElementMatrix* CreateKMatrixDiagnosticMacAyealViscous(void);
     196                ElementMatrix* CreateKMatrixDiagnosticMacAyealFriction(void);
     197                ElementMatrix* CreateKMatrixDiagnosticHutter(void);
     198                ElementVector* CreatePVectorDiagnosticMacAyeal(void);
     199                ElementVector* CreatePVectorDiagnosticHutter(void);
    195200                void      GetSolutionFromInputsDiagnosticHoriz(Vec solution);
    196201                void      GetSolutionFromInputsDiagnosticHutter(Vec solution);
    197                 void      GetSolutionFromInputsHydrology(Vec solution);
    198                 void    GetStrainRate2d(double* epsilon,double* xyz_list, GaussTria* gauss, Input* vx_input, Input* vy_input);
     202                void      InputUpdateFromSolutionDiagnosticHoriz( double* solution);
     203                void      InputUpdateFromSolutionDiagnosticHutter( double* solution);
     204                #endif
     205
     206                #ifdef _HAVE_CONTROL_
     207                ElementMatrix* CreateKMatrixAdjointBalancethickness(void);
     208                ElementVector* CreatePVectorAdjointHoriz(void);
     209                ElementVector* CreatePVectorAdjointStokes(void);
     210                ElementVector* CreatePVectorAdjointBalancethickness(void);
    199211                void      InputUpdateFromSolutionAdjointBalancethickness( double* solution);
    200212                void      InputUpdateFromSolutionAdjointHoriz( double* solution);
    201                 void      InputUpdateFromSolutionDiagnosticHoriz( double* solution);
    202                 void      InputUpdateFromSolutionDiagnosticHutter( double* solution);
    203                 void      InputUpdateFromSolutionOneDof(double* solution,int enum_type);
    204                 void      InputUpdateFromSolutionPrognostic(double* solution);
     213                #endif
     214
     215                #ifdef _HAVE_HYDROLOGY_
     216                ElementMatrix* CreateKMatrixHydrology(void);
     217                ElementVector* CreatePVectorHydrology(void);
     218                void      CreateHydrologyWaterVelocityInput(void);
     219                void      GetSolutionFromInputsHydrology(Vec solution);
    205220                void      InputUpdateFromSolutionHydrology(double* solution);
    206                 bool      IsInput(int name);
    207                 void      SetClone(int* minranks);
    208                 void      SurfaceNormal(double* surface_normal, double xyz_list[3][3]);
     221                #endif
     222                #ifdef _HAVE_BALANCED_
     223                #endif
     224
    209225                /*}}}*/
    210226
  • issm/trunk/src/c/objects/Loads/Icefront.cpp

    r9725 r9775  
    436436                case MacAyeal2dIceFrontEnum:
    437437                        return CreatePVectorDiagnosticMacAyeal2d();
     438        #ifdef _HAVE_THREED_
    438439                case MacAyeal3dIceFrontEnum:
    439440                        return CreatePVectorDiagnosticMacAyeal3d();
     
    442443                case StokesIceFrontEnum:
    443444                        return CreatePVectorDiagnosticStokes();
     445            #endif
    444446                default:
    445447                        _error_("Icefront type %s not supported yet",EnumToStringx(type));
     
    532534}
    533535/*}}}*/
     536#ifdef _HAVE_THREED_
    534537/*FUNCTION Icefront::CreatePVectorDiagnosticMacAyeal3d{{{1*/
    535538ElementVector* Icefront::CreatePVectorDiagnosticMacAyeal3d(void){
     
    709712}
    710713/*}}}*/
     714#endif
    711715/*FUNCTION Icefront::GetDofList {{{1*/
    712716void  Icefront::GetDofList(int** pdoflist,int approximation_enum,int setenum){
  • issm/trunk/src/c/objects/Loads/Icefront.h

    r8800 r9775  
    8181                ElementVector* CreatePVectorDiagnosticHoriz(void);
    8282                ElementVector* CreatePVectorDiagnosticMacAyeal2d(void);
     83        #ifdef _HAVE_THREED_
    8384                ElementVector* CreatePVectorDiagnosticMacAyeal3d(void);
    8485                ElementVector* CreatePVectorDiagnosticPattyn(void);
    8586                ElementVector* CreatePVectorDiagnosticStokes(void);
     87            #endif
    8688                void  GetDofList(int** pdoflist,int approximation_enum,int setenum);
    8789                void GetSegmentNormal(double* normal,double xyz_list[2][3]);
  • issm/trunk/src/c/objects/Loads/Riftfront.cpp

    r9725 r9775  
    851851}
    852852/*}}}1*/
    853 /*FUNCTION Riftfront::OutputProperties {{{1*/
    854 void  Riftfront::OutputProperties(Vec riftproperties){
    855 
    856         int row_id=0;
    857         double value;
    858 
    859         /*recover id of penalty: */
    860         row_id=this->Id()-1; //c indexing, ids were matlab indexed
    861         value=(double)this->fraction;
    862 
    863         /*Plug id and fraction  into riftproperties matrix: */
    864         VecSetValues(riftproperties,1,&row_id,&value,INSERT_VALUES);
    865 }
    866 /*}}}1*/
    867853/*FUNCTION Riftfront::Penetration {{{1*/
    868854int   Riftfront::Penetration(double* ppenetration){
  • issm/trunk/src/c/objects/Loads/Riftfront.h

    r8800 r9775  
    9898                int   PotentialUnstableConstraint(int* punstable);
    9999                int   IsMaterialStable(void);
    100                 void  OutputProperties(Vec riftproperties);
    101100                bool  IsInput(int name);
    102101                /*}}}*/
  • issm/trunk/src/c/objects/Materials/Matice.cpp

    r9761 r9775  
    706706
    707707        /*if 3d*/
     708        #ifdef _HAVE_THREED_
    708709        else if(dim==3){
    709710
     
    745746                #endif
    746747        }
     748        #endif
    747749        else{
    748750                _error_(" Mesh type not supported yet!");
  • issm/trunk/src/c/solutions/CorePointerFromSolutionEnum.cpp

    r9761 r9775  
    2626       
    2727                case DiagnosticSolutionEnum:
     28                        #ifdef _HAVE_DIAGNOSTIC_
    2829                        solutioncore=&diagnostic_core;
     30                        #else
     31                        _error_("ISSM was not compiled with diagnostic capabilities. Exiting");
     32                        #endif
    2933                        break;
    3034                case SteadystateSolutionEnum:
     35                        #ifdef _HAVE_STEADYSTATE_
    3136                        solutioncore=&steadystate_core;
     37                        _error_("ISSM was not compiled with steady state capabilities. Exiting");
     38                        #endif
    3239                        break;
    3340                case ThermalSolutionEnum:
     
    4552                        #endif
    4653                        break;
    47                 case PrognosticSolutionEnum:
    48                         solutioncore=&prognostic_core;
     54                case BalancethicknessSolutionEnum:
     55                        #ifdef _HAVE_BALANCED_
     56                        solutioncore=&balancethickness_core;
     57                        #else
     58                        _error_("ISSM was not compiled with balanced capabilities. Exiting");
     59                        #endif
    4960                        break;
    50                 case BalancethicknessSolutionEnum:
    51                         solutioncore=&balancethickness_core;
     61                case HydrologySolutionEnum:
     62                        #ifdef _HAVE_HYDROLOGY_
     63                        solutioncore=&hydrology_core;
     64                        #else
     65                        _error_("ISSM was not compiled with hydrology capabilities. Exiting");
     66                        #endif
    5267                        break;
    5368                case SurfaceSlopeSolutionEnum:
     69                        #ifdef _HAVE_SLOPE_
    5470                        solutioncore=&surfaceslope_core;
     71                        #else
     72                        _error_("ISSM was not compiled with slope capabilities. Exiting");
     73                        #endif
    5574                        break;
    5675                case BedSlopeSolutionEnum:
     76                        #ifdef _HAVE_SLOPE_
    5777                        solutioncore=&bedslope_core;
     78                        #else
     79                        _error_("ISSM was not compiled with slope capabilities. Exiting");
     80                        #endif
    5881                        break;
    5982                case TransientSolutionEnum:
     83                        #ifdef _HAVE_TRANSIENT_
    6084                        solutioncore=&transient_core;
     85                        #else
     86                        _error_("ISSM was not compiled with transient capabilities. Exiting");
     87                        #endif
    6188                        break;
    6289                case GroundinglineMigration2dSolutionEnum:
     90                        #ifdef _HAVE_GROUNDINGLINE_
    6391                        solutioncore=&groundinglinemigration2d_core;
     92                        #else
     93                        _error_("ISSM was not compiled with grounding line migration capabilities. Exiting");
     94                        #endif
    6495                        break;
    65                 case HydrologySolutionEnum:
    66                         solutioncore=&hydrology_core;
     96                case PrognosticSolutionEnum:
     97                        #ifdef _HAVE_PROGNOSTIC_
     98                        solutioncore=&prognostic_core;
     99                        #else
     100                        _error_("ISSM was not compiled with prognostic capabilities. Exiting");
     101                        #endif
    67102                        break;
    68103                default:
  • issm/trunk/src/c/solutions/transient_core.cpp

    r9761 r9775  
    8181                if(isdiagnostic){
    8282                        _printf_(VerboseSolution(),"   computing new velocity\n");
     83                        #ifdef _HAVE_DIAGNOSTIC_
    8384                        diagnostic_core(femmodel);
     85                        #else
     86                        _error_("ISSM was not compiled with diagnostic capabilities. Exiting");
     87                        #endif
     88
    8489                }
    8590
     
    9499                        if(dim==3) _error_("Grounding line migration not implemented in 3d");
    95100                        _printf_(VerboseSolution(),"   computing new grounding line position\n");
     101                        #ifdef _HAVE_DIAGNOSTIC_
    96102                        GroundingLineMigrationx(femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters);
     103                        #else
     104                        _error_("ISSM was not compiled with grounding line migration capabilities. Exiting");
     105                        #endif
     106
    97107                }
    98108
  • issm/trunk/src/mex/Makefile.am

    r9570 r9775  
    5454                                NodesDof\
    5555                                Orth\
    56                                 OutputRifts\
    5756                                OutputResults\
    5857                                ParsePetscOptions\
     
    261260                          Orth/Orth.h
    262261
    263 OutputRifts_SOURCES = OutputRifts/OutputRifts.cpp\
    264                           OutputRifts/OutputRifts.h
    265 
    266262OutputResults_SOURCES = OutputResults/OutputResults.cpp\
    267263                          OutputResults/OutputResults.h
Note: See TracChangeset for help on using the changeset viewer.