Changeset 9775
- Timestamp:
- 09/12/11 12:42:33 (14 years ago)
- Location:
- issm/trunk/src
- Files:
-
- 23 edited
Legend:
- Unmodified
- Added
- Removed
-
issm/trunk/src/ad/eraselinks.sh
r9773 r9775 7 7 rm shared 8 8 rm toolkits 9 rm iorm EnumDefinitions 9 rm io 10 rm EnumDefinitions 10 11 rm modules 11 12 rm solutions -
issm/trunk/src/c/Container/DataSet.cpp
r9761 r9775 229 229 dataset->AddObject(triavertexinput);} 230 230 break; 231 #ifdef _HAVE_THREED_ 231 232 case PentaVertexInputEnum:{ 232 233 PentaVertexInput* pentavertexinput=NULL; … … 235 236 dataset->AddObject(pentavertexinput);} 236 237 break; 238 #endif 237 239 case TransientInputEnum:{ 238 240 TransientInput* transientinput=NULL; … … 261 263 dataset->AddObject(triavertexelementresult);} 262 264 break; 265 #ifdef _HAVE_THREED_ 263 266 case PentaVertexElementResultEnum:{ 264 267 PentaVertexElementResult* pentavertexelementresult=NULL; … … 273 276 dataset->AddObject(penta);} 274 277 break; 278 #endif 275 279 case MaticeEnum:{ 276 280 Matice* matice=NULL; … … 327 331 dataset->AddObject(numericalflux);} 328 332 break; 333 #ifdef _HAVE_RIFTS_ 329 334 case RiftfrontEnum:{ 330 335 Riftfront* riftfront=NULL; … … 333 338 dataset->AddObject(riftfront);} 334 339 break; 340 #endif 335 341 case DoubleInputEnum:{ 336 342 DoubleInput* doubleinput=NULL; -
issm/trunk/src/c/Container/Loads.cpp
r9320 r9775 78 78 } 79 79 /*}}}*/ 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 /*}}}*/97 80 /*FUNCTION Loads::SetCurrentConfiguration{{{1*/ 98 81 void Loads::SetCurrentConfiguration(Elements* elements,Loads* loads, Nodes* nodes, Vertices* vertices, Materials* materials,Parameters* parameters){ -
issm/trunk/src/c/Container/Loads.h
r6411 r9775 28 28 void Configure(Elements* elements,Loads* loads, Nodes* nodes, Vertices* vertices, Materials* materials,Parameters* parameters); 29 29 int NumberOfLoads(void); 30 void OutputRifts(Vec riftproperties);31 30 void SetCurrentConfiguration(Elements* elements,Loads* loads, Nodes* nodes, Vertices* vertices, Materials* materials,Parameters* parameters); 32 31 /*}}}*/ -
issm/trunk/src/c/Makefile.am
r9761 r9775 1 1 INCLUDES = @DAKOTAINCL@ @PETSCINCL@ @SLEPCINCL@ @MPIINCL@ @MATLABINCL@ @METISINCL@ @CHACOINCL@ @SCOTCHINCL@ @PLAPACKINCL@ @BLASLAPACKINCL@ @MKLINCL@ @MUMPSINCL@ @TRIANGLEINCL@ @HYPREINCL@ @MLINCL@ @TAOINCL@ 2 2 3 #Library declaration {{{1 3 4 #Compile serial library, and then try and compile parallel library 4 5 if NOSERIAL … … 16 17 endif 17 18 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 23 23 libISSM_a_SOURCES = ./include/macros.h\ 24 24 ./include/typedefs.h\ … … 689 689 ./modules/InputConvergencex/InputConvergencex.cpp\ 690 690 ./modules/InputConvergencex/InputConvergencex.h\ 691 ./modules/OutputRiftsx/OutputRiftsx.h\692 ./modules/OutputRiftsx/OutputRiftsx.cpp\693 691 ./modules/Bamgx/Bamgx.cpp\ 694 692 ./modules/Bamgx/Bamgx.h\ … … 712 710 endif 713 711 714 #Parallel compilation 712 #}}} 713 714 #For parallel compilation 715 #ISSM parallel library {{{1 715 716 libpISSM_a_SOURCES = ./include/macros.h\ 716 717 ./include/typedefs.h\ 717 718 ./include/types.h\ 718 ./include/globals.h\719 719 ./include/include.h\ 720 720 ./objects/objects.h\ 721 721 ./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\772 722 ./objects/Gauss/GaussTria.h\ 773 723 ./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\838 724 ./objects/Update.h\ 839 725 ./objects/Element.h\ … … 848 734 ./objects/Loads/Friction.h\ 849 735 ./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\ 852 740 ./objects/DofIndexing.h\ 853 741 ./objects/DofIndexing.cpp\ … … 869 757 ./objects/ElementResults/TriaVertexElementResult.h\ 870 758 ./objects/ElementResults/TriaVertexElementResult.cpp\ 871 ./objects/ElementResults/PentaVertexElementResult.h\872 ./objects/ElementResults/PentaVertexElementResult.cpp\873 759 ./objects/ElementResults/BoolElementResult.h\ 874 760 ./objects/ElementResults/BoolElementResult.cpp\ … … 898 784 ./objects/Inputs/TriaVertexInput.h\ 899 785 ./objects/Inputs/TriaVertexInput.cpp\ 900 ./objects/Inputs/PentaVertexInput.h\901 ./objects/Inputs/PentaVertexInput.cpp\902 786 ./objects/Inputs/BoolInput.h\ 903 787 ./objects/Inputs/BoolInput.cpp\ … … 906 790 ./objects/Inputs/DoubleInput.h\ 907 791 ./objects/Inputs/DoubleInput.cpp\ 908 ./objects/Inputs/ControlInput.h\909 ./objects/Inputs/ControlInput.cpp\910 792 ./objects/Inputs/DatasetInput.h\ 911 793 ./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\920 794 ./objects/Materials/Matice.h\ 921 795 ./objects/Materials/Matice.cpp\ … … 927 801 ./objects/Constraints/SpcDynamic.cpp\ 928 802 ./objects/Constraints/SpcDynamic.h\ 929 ./objects/Constraints/SpcTransient.cpp\930 ./objects/Constraints/SpcTransient.h\931 803 ./objects/Loads/Penpair.cpp\ 932 804 ./objects/Loads/Penpair.h\ … … 935 807 ./objects/Loads/Icefront.cpp\ 936 808 ./objects/Loads/Icefront.h\ 937 ./objects/Loads/Riftfront.cpp\938 ./objects/Loads/Riftfront.h\939 809 ./objects/Loads/Numericalflux.cpp\ 940 810 ./objects/Loads/Numericalflux.h\ … … 994 864 ./Container/Vertices.cpp\ 995 865 ./shared/shared.h\ 996 ./shared/Threads/issm_threads.h\997 ./shared/Threads/LaunchThread.cpp\998 ./shared/Threads/PartitionRange.cpp\999 866 ./shared/Alloc/alloc.h\ 1000 867 ./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\1006 868 ./shared/Matrix/matrix.h\ 1007 869 ./shared/Matrix/MatrixUtils.cpp\ … … 1016 878 ./shared/Numerics/cross.cpp\ 1017 879 ./shared/Numerics/norm.cpp\ 1018 ./shared/Numerics/BrentSearch.cpp\1019 ./shared/Numerics/OptimalSearch.cpp\1020 ./shared/Numerics/OptFunc.cpp\1021 880 ./shared/Numerics/extrema.cpp\ 1022 881 ./shared/Numerics/UnitConversion.cpp\ … … 1025 884 ./shared/Exceptions/Exceptions.cpp\ 1026 885 ./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\1038 886 ./shared/Sorting/binary_search.cpp\ 1039 887 ./shared/Sorting/sorting.h\ … … 1046 894 ./shared/Elements/GetNumberOfDofs.cpp\ 1047 895 ./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 \1057 896 ./toolkits/petsc\ 1058 897 ./toolkits/petsc/patches\ … … 1098 937 ./io/Disk/pfopen.cpp\ 1099 938 ./io/Disk/pfclose.cpp\ 1100 ./io/Matlab/matlabio.h\1101 ./io/Matlab/WriteMatlabData.cpp\1102 ./io/Matlab/FetchMatlabData.cpp\1103 ./io/Matlab/OptionParse.cpp\1104 939 ./io/PrintfFunction.cpp\ 1105 940 ./EnumDefinitions/EnumDefinitions.h\ 1106 941 ./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\1118 942 ./modules/ModelProcessorx/ModelProcessorx.h\ 1119 943 ./modules/ModelProcessorx/ModelProcessorx.cpp\ … … 1128 952 ./modules/ModelProcessorx/CreateNumberNodeToElementConnectivity.cpp\ 1129 953 ./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\1178 954 ./modules/ParsePetscOptionsx/ParsePetscOptionsx.h\ 1179 955 ./modules/ParsePetscOptionsx/ParsePetscOptionsx.cpp\ … … 1182 958 ./modules/NodalValuex/NodalValuex.h\ 1183 959 ./modules/NodalValuex/NodalValuex.cpp\ 1184 ./modules/TriaSearchx/TriaSearchx.h\1185 ./modules/TriaSearchx/TriaSearchx.cpp\1186 960 ./modules/VerticesDofx/VerticesDofx.h\ 1187 961 ./modules/VerticesDofx/VerticesDofx.cpp\ 1188 962 ./modules/OutputResultsx/OutputResultsx.h\ 1189 963 ./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\1226 964 ./modules/InputDuplicatex/InputDuplicatex.h\ 1227 965 ./modules/InputDuplicatex/InputDuplicatex.cpp\ 1228 966 ./modules/InputScalex/InputScalex.h\ 1229 967 ./modules/InputScalex/InputScalex.cpp\ 1230 ./modules/InputControlUpdatex/InputControlUpdatex.h\1231 ./modules/InputControlUpdatex/InputControlUpdatex.cpp\1232 968 ./modules/SurfaceAreax/SurfaceAreax.h\ 1233 969 ./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\1248 970 ./modules/CreateNodalConstraintsx/CreateNodalConstraintsx.h\ 1249 971 ./modules/CreateNodalConstraintsx/CreateNodalConstraintsx.cpp\ 1250 ./modules/Orthx/Orthx.h\1251 ./modules/Orthx/Orthx.cpp\1252 972 ./modules/UpdateDynamicConstraintsx/UpdateDynamicConstraintsx.h\ 1253 973 ./modules/UpdateDynamicConstraintsx/UpdateDynamicConstraintsx.cpp\ 1254 ./modules/Gradjx/Gradjx.h\1255 ./modules/Gradjx/Gradjx.cpp\1256 974 ./modules/IoModelToConstraintsx/IoModelToConstraintsx.h\ 1257 975 ./modules/IoModelToConstraintsx/IoModelToConstraintsx.cpp\ 1258 976 ./modules/InputUpdateFromConstantx/InputUpdateFromConstantx.h\ 1259 977 ./modules/InputUpdateFromConstantx/InputUpdateFromConstantx.cpp\ 1260 ./modules/InputUpdateFromDakotax/InputUpdateFromDakotax.h\1261 ./modules/InputUpdateFromDakotax/InputUpdateFromDakotax.cpp\1262 978 ./modules/InputUpdateFromSolutionx/InputUpdateFromSolutionx.h\ 1263 979 ./modules/InputUpdateFromSolutionx/InputUpdateFromSolutionx.cpp\ 1264 ./modules/DakotaResponsesx/DakotaResponsesx.h\1265 ./modules/DakotaResponsesx/DakotaResponsesx.cpp\1266 980 ./modules/GetSolutionFromInputsx/GetSolutionFromInputsx.h\ 1267 981 ./modules/GetSolutionFromInputsx/GetSolutionFromInputsx.cpp\ … … 1270 984 ./modules/InputUpdateFromVectorx/InputUpdateFromVectorx.h\ 1271 985 ./modules/InputUpdateFromVectorx/InputUpdateFromVectorx.cpp\ 1272 ./modules/InputUpdateFromVectorDakotax/InputUpdateFromVectorDakotax.h\1273 ./modules/InputUpdateFromVectorDakotax/InputUpdateFromVectorDakotax.cpp\1274 986 ./modules/InputArtificialNoisex/InputArtificialNoisex.h\ 1275 987 ./modules/InputArtificialNoisex/InputArtificialNoisex.cpp\ … … 1288 1000 ./modules/UpdateConstraintsx/UpdateConstraintsx.h\ 1289 1001 ./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\1307 1002 ./modules/MeshPartitionx/MeshPartitionx.cpp\ 1308 1003 ./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\1321 1004 ./modules/Reducevectorgtofx/Reducevectorgtofx.cpp\ 1322 1005 ./modules/Reducevectorgtofx/Reducevectorgtofx.h\ … … 1327 1010 ./modules/StringToEnumx/StringToEnumx.cpp\ 1328 1011 ./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\1337 1012 ./modules/SystemMatricesx/SystemMatricesx.cpp\ 1338 1013 ./modules/SystemMatricesx/SystemMatricesx.h\ … … 1340 1015 ./modules/ConstraintsStatex/ConstraintsStatex.h\ 1341 1016 ./modules/ConstraintsStatex/ConstraintsStateLocal.h\ 1342 ./modules/ConstraintsStatex/RiftConstraintsState.cpp\1343 ./modules/ConstraintsStatex/ThermalConstraintsState.cpp\1344 ./modules/ConstraintsStatex/ThermalIsPresent.cpp\1345 1017 ./modules/Responsex/Responsex.h\ 1346 1018 ./modules/Responsex/Responsex.cpp\ … … 1349 1021 ./modules/ResetConstraintsx/ResetConstraintsx.h\ 1350 1022 ./modules/ResetConstraintsx/ResetConstraintsx.cpp\ 1351 ./modules/ResetConstraintsx/ThermalConstraintsReset.cpp\1352 1023 ./modules/Solverx/Solverx.cpp\ 1353 1024 ./modules/Solverx/Solverx.h\ … … 1355 1026 ./modules/VecMergex/VecMergex.cpp\ 1356 1027 ./modules/VecMergex/VecMergex.h\ 1357 ./modules/Scotchx/Scotchx.cpp\1358 ./modules/Scotchx/Scotchx.h\1359 1028 ./modules/Mergesolutionfromftogx/Mergesolutionfromftogx.cpp\ 1360 1029 ./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\1368 1030 ./modules/InputToResultx/InputToResultx.cpp\ 1369 1031 ./modules/InputToResultx/InputToResultx.h\ 1370 1032 ./modules/InputConvergencex/InputConvergencex.cpp\ 1371 1033 ./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\1383 1034 ./solutions/convergence.cpp\ 1384 ./solutions/thermal_core.cpp\1385 ./solutions/thermal_core_step.cpp\1386 ./solutions/enthalpy_core.cpp\1387 1035 ./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\1406 1036 ./solutions/ResetBoundaryConditions.cpp\ 1407 1037 ./solutions/AnalysisConfiguration.cpp\ 1408 1038 ./solutions/CorePointerFromSolutionEnum.cpp\ 1409 ./solutions/AdjointCorePointerFromSolutionEnum.cpp\1410 1039 ./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 1043 libpISSM_a_CXXFLAGS = -fPIC -D_PARALLEL_ -D_C_ $(CXXOPTFLAGS) 1044 #}}} 1045 #Overload library, to overload any non-standard symbols. {{{1 1046 libOverload_a_SOURCES = ./shared/String/stricmp.c 1047 libOverload_a_CFLAGS = -fPIC -D_PARALLEL_ -D_C_ $(COPTFLAGS) 1048 #}}} 1049 #DAKOTA sources {{{1 1050 if DAKOTA 1051 libpISSM_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 1071 endif 1072 #}}} 1073 #Transient sources {{{1 1074 if TRANSIENT 1075 libpISSM_a_SOURCES += ./solutions/transient_core.cpp\ 1076 ./modules/ModelProcessorx/Transient/UpdateElementsTransient.cpp 1077 endif 1078 #}}} 1079 #Steadystate sources {{{1 1080 if STEADYSTATE 1081 libpISSM_a_SOURCES += ./solutions/steadystate_core.cpp\ 1082 ./solutions/steadystateconvergence.cpp 1083 endif 1084 #}}} 1085 #Prognostic sources {{{1 1086 if PROGNOSTIC 1087 libpISSM_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 1093 endif 1094 #}}} 1095 #Thermal sources {{{1 1096 if THERMAL 1097 libpISSM_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 1116 endif 1117 #}}} 1118 #Control sources {{{1 1119 if CONTROL 1120 libpISSM_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 1169 endif 1170 #}}} 1171 #Hydrology sources {{{1 1172 if HYDROLOGY 1173 libpISSM_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 1179 endif 1180 #}}} 1181 #Diagnostic sources {{{1 1182 if DIAGNOSTIC 1183 libpISSM_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 1197 endif 1198 #}}} 1199 #Balanced sources {{{1 1200 if BALANCED 1201 libpISSM_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 1206 endif 1207 #}}} 1208 #Responses sources {{{1 1209 if RESPONSES 1210 libpISSM_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 1236 endif 1237 #}}} 1238 #Slope sources {{{1 1239 if SLOPE 1240 libpISSM_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 1250 endif 1251 #}}} 1252 #GroundingLine sources {{{1 1253 if GROUNDINGLINE 1254 libpISSM_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 1259 endif 1260 #}}} 1261 #Rifts sources {{{1 1262 if RIFTS 1263 libpISSM_a_SOURCES += ./objects/Loads/Riftfront.cpp\ 1264 ./objects/Loads/Riftfront.h\ 1265 ./modules/ConstraintsStatex/RiftConstraintsState.cpp 1266 endif 1267 #}}} 1268 #3D sources {{{1 1269 if THREED 1270 libpISSM_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 1282 endif 1283 #}}} 1284 1285 #Executable {{{1 1421 1286 1422 1287 if NOPARALLEL … … 1426 1291 endif 1427 1292 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 1294 LDADD = ./libpISSM.a ./libOverload.a 1295 1296 if AD 1297 LDADD += ./libAD.a 1298 endif 1299 1300 #External packages 1301 LDADD += $(PETSCLIB) $(TAOLIB) $(FLIBS) $(PLAPACKLIB) $(MUMPSLIB) $(SCALAPACKLIB) $(BLACSLIB) $(HYPRELIB) $(MLLIB) $(DAKOTALIB) $(METISLIB) $(CHACOLIB) $(SCOTCHLIB) $(BLASLAPACKLIB) $(MKLLIB) $(MPILIB) $(MATHLIB) $(FORTRANLIB) $(GRAPHICSLIB) $(MULTITHREADINGLIB) $(ADICLIB) 1302 1429 1303 1430 1304 issm_exe_SOURCES = solutions/issm.cpp 1431 issm_exe_CXXFLAGS= -fPIC -D_PARALLEL_ $(CXXOPTFLAGS) $(COPTFLAGS) 1305 issm_exe_CXXFLAGS= -fPIC -D_PARALLEL_ $(CXXOPTFLAGS) $(COPTFLAGS) 1306 1307 #}}} 1308 -
issm/trunk/src/c/modules/Dakotax/SpawnCoreParallel.cpp
r9761 r9775 69 69 _printf_(VerboseQmu(),"%s%s%s\n","Starting ",EnumToStringx(solution_type)," core:"); 70 70 CorePointerFromSolutionEnum(&solutioncore,femmodel->parameters,solution_type); 71 #ifdef _HAVE_CONTROL_ 71 72 if(control_analysis)solutioncore=&control_core; 73 #else 74 _error_("ISSM was not compiled with control capabilities, exiting!"); 75 #endif 72 76 73 77 /*Run the core solution sequence: */ -
issm/trunk/src/c/modules/ModelProcessorx/CreateDataSets.cpp
r9761 r9775 32 32 /*Now, branch onto analysis dependent model generation: */ 33 33 switch(analysis_type){ 34 35 #ifdef _HAVE_DIAGNOSTIC_ 34 36 case DiagnosticHorizAnalysisEnum: 35 37 CreateNodesDiagnosticHoriz(pnodes, iomodel); … … 52 54 UpdateElementsDiagnosticHutter(elements,iomodel,analysis_counter,analysis_type); 53 55 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_ 69 59 case HydrologyAnalysisEnum: 70 60 CreateNodesHydrology(pnodes, iomodel); … … 73 63 UpdateElementsHydrology(elements,iomodel,analysis_counter,analysis_type); 74 64 break; 65 #endif 75 66 76 67 #ifdef _HAVE_THERMAL_ … … 97 88 #endif 98 89 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_ 99 116 case PrognosticAnalysisEnum: 100 117 CreateNodesPrognostic(pnodes, iomodel); … … 103 120 UpdateElementsPrognostic(elements,iomodel,analysis_counter,analysis_type); 104 121 break; 122 #endif 105 123 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;112 124 113 125 default: … … 124 136 125 137 /*Update Elements in case we are running a transient solution: */ 138 #ifdef _HAVE_TRANSIENT_ 126 139 parameters=*pparameters; 127 140 if(analysis_counter==(nummodels-1)&& solution_type==TransientSolutionEnum){ 128 141 UpdateElementsTransient(elements,parameters,iomodel,analysis_counter,analysis_type); 129 142 } 143 #endif 130 144 131 145 /*Sort datasets: */ -
issm/trunk/src/c/modules/ModelProcessorx/CreateElementsVerticesAndMaterials.cpp
r9734 r9775 46 46 /*Fetch data needed: */ 47 47 iomodel->FetchData(4,MeshElementsEnum,MeshElementconnectivityEnum,MaterialsRheologyBEnum,MaterialsRheologyNEnum); 48 #ifdef _HAVE_THREED_ 48 49 if(dim==3) iomodel->FetchData(2,MeshUpperelementsEnum,MeshLowerelementsEnum); 50 #endif 49 51 if(control_analysis)iomodel->FetchData(3,InversionControlParametersEnum,InversionMinParametersEnum,InversionMaxParametersEnum); 50 52 … … 55 57 /*Create and add tria element to elements dataset: */ 56 58 if(dim==2) elements->AddObject(new Tria(i+1,i,i,iomodel,nummodels)); 59 #ifdef _HAVE_THREED_ 57 60 else elements->AddObject(new Penta(i+1,i,i,iomodel,nummodels)); 61 #endif 58 62 59 63 /*Create and add material property to materials dataset: */ -
issm/trunk/src/c/modules/Responsex/Responsex.cpp
r9636 r9775 19 19 20 20 switch (StringToEnumx(response_descriptor)){ 21 21 22 #ifdef _HAVE_RESPONSES_ 22 23 case MinVelEnum: MinVelx( responses, elements,nodes, vertices, loads, materials, parameters,process_units); break; 23 24 case MaxVelEnum: MaxVelx( responses, elements,nodes, vertices, loads, materials, parameters,process_units); break; … … 44 45 case FrictionCoefficientEnum:NodalValuex(responses, FrictionCoefficientEnum,elements,nodes, vertices, loads, materials, parameters,process_units); break; 45 46 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 46 50 } 47 51 -
issm/trunk/src/c/modules/modules.h
r9571 r9775 84 84 #include "./Orthx/Orthx.h" 85 85 #include "./OutputResultsx/OutputResultsx.h" 86 #include "./OutputRiftsx/OutputRiftsx.h"87 86 #include "./ConstraintsStatex/ConstraintsStatex.h" 88 87 #include "./PointCloudFindNeighborsx/PointCloudFindNeighborsx.h" -
issm/trunk/src/c/objects/Elements/Element.h
r9761 r9775 69 69 virtual void InputCreate(double scalar,int name,int code)=0; 70 70 virtual void InputCreate(double* vector, int index,IoModel* iomodel,int M,int N,int vector_type,int vector_enum,int code)=0; 71 71 virtual void ProcessResultsUnits(void)=0; 72 72 virtual void RequestedOutput(int output_enum,int step,double time)=0; 73 73 virtual void MinVel(double* pminvel, bool process_units)=0; -
issm/trunk/src/c/objects/Elements/Penta.cpp
r9761 r9775 524 524 } 525 525 /*}}}*/ 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 approximation537 }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 /*}}}*/565 526 /*FUNCTION Penta::CreateKMatrix {{{1*/ 566 527 void Penta::CreateKMatrix(Mat Kff, Mat Kfs,Vec df){ … … 581 542 /*Just branch to the correct element stiffness matrix generator, according to the type of analysis we are carrying out: */ 582 543 switch(analysis_type){ 544 #ifdef _HAVE_DIAGNOSTIC_ 583 545 case DiagnosticHorizAnalysisEnum: case AdjointHorizAnalysisEnum: 584 546 Ke=CreateKMatrixDiagnosticHoriz(); De=CreateDVectorDiagnosticHoriz(); … … 590 552 Ke=CreateKMatrixDiagnosticVert(); 591 553 break; 554 #endif 592 555 case BedSlopeXAnalysisEnum: case SurfaceSlopeXAnalysisEnum: case BedSlopeYAnalysisEnum: case SurfaceSlopeYAnalysisEnum: 593 556 Ke=CreateKMatrixSlope(); … … 596 559 Ke=CreateKMatrixPrognostic(); 597 560 break; 561 #ifdef _HAVE_BALANCED_ 598 562 case BalancethicknessAnalysisEnum: 599 563 Ke=CreateKMatrixBalancethickness(); 600 564 break; 565 #endif 601 566 #ifdef _HAVE_THERMAL_ 602 567 case ThermalAnalysisEnum: … … 626 591 } 627 592 /*}}}*/ 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*/ 594 ElementMatrix* Penta::CreateKMatrixPrognostic(void){ 595 634 596 if (!IsOnBed()) return NULL; 635 597 … … 638 600 this->InputDepthAverageAtBase(VyEnum,VyAverageEnum); 639 601 640 /*Spawn Tria element from the base of the Penta: */641 602 Tria* tria=(Tria*)SpawnTria(0,1,2); //nodes 0, 1 and 2 make the new tria. 642 ElementMatrix* Ke=tria->CreateKMatrix Balancethickness();603 ElementMatrix* Ke=tria->CreateKMatrixPrognostic(); 643 604 delete tria->matice; delete tria; 644 605 … … 651 612 } 652 613 /*}}}*/ 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; //viscosity679 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 matrix686 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 drag763 double DL_scalar;764 double Ke_gg[numdof][numdof] ={0.0};765 double Ke_gg_gaussian[numdof][numdof]; //stiffness matrix contribution from drag766 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; //viscosity856 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 matrix866 double Ke_gg2[numdofm][numdofs]={0.0}; //local element stiffness matrix867 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 connectivity1150 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 the1164 bedrock, in which case we spawn a tria element using the 3 first nodes, and use it to build1165 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 stokes1209 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 use1289 * the tria functionality to build a friction stiffness matrix on these 31290 * 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; //viscosity1358 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 drag1425 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 bubble1523 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 /*}}}*/1783 614 /*FUNCTION Penta::CreateKMatrixSlope {{{1*/ 1784 615 ElementMatrix* Penta::CreateKMatrixSlope(void){ … … 1794 625 } 1795 626 /*}}}*/ 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 point2818 * 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 point2893 * 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 #endif2926 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 result3285 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/dki3298 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 now3345 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 now3362 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 surface3498 * -> 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 surface3535 * -> 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 surface3572 * -> 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 surface3611 * -> 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 surface3648 * -> 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 tria3706 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 tria3721 J=tria->RheologyBbarAbsGradient(process_units,weight_index);3722 delete tria->matice; delete tria;3723 return J;3724 }3725 /*}}}*/3726 3727 #endif3728 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 else3786 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 else3807 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 #endif3844 3845 627 /*FUNCTION Penta::CreatePVector {{{1*/ 3846 628 void Penta::CreatePVector(Vec pf){ … … 3860 642 /*Just branch to the correct element stiffness matrix generator, according to the type of analysis we are carrying out: */ 3861 643 switch(analysis_type){ 644 #ifdef _HAVE_DIAGNOSTIC_ 3862 645 case DiagnosticHorizAnalysisEnum: 3863 646 pe=CreatePVectorDiagnosticHoriz(); 3864 647 break; 3865 #ifdef _HAVE_CONTROL_3866 case AdjointHorizAnalysisEnum:3867 pe=CreatePVectorAdjointHoriz();3868 break;3869 #endif3870 648 case DiagnosticHutterAnalysisEnum: 3871 649 pe=CreatePVectorDiagnosticHutter(); … … 3874 652 pe=CreatePVectorDiagnosticVert(); 3875 653 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(); 3878 658 break; 3879 case PrognosticAnalysisEnum: 3880 pe=CreatePVectorPrognostic(); 3881 break; 3882 case BalancethicknessAnalysisEnum: 3883 pe=CreatePVectorBalancethickness(); 3884 break; 659 #endif 3885 660 #ifdef _HAVE_THERMAL_ 3886 661 case ThermalAnalysisEnum: … … 3894 669 break; 3895 670 #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 3896 682 default: 3897 683 _error_("analysis %i (%s) not supported yet",analysis_type,EnumToStringx(analysis_type)); … … 3903 689 delete pe; 3904 690 } 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 penta3958 double dbasis[3][6]; //for the six nodes of the penta3959 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 penta4020 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 penta4103 double dbasis[3][6]; //for the six nodes of the penta4104 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 penta4165 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 it4361 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 surface4367 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 bubble4468 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 bubble4474 double Ke_temp[numdofbubble][3]={0.0}; //for the six nodes and the bubble4475 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 penta4546 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 equilibrium4579 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;4731 691 } 4732 692 /*}}}*/ … … 5029 989 5030 990 /*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: 5032 994 int approximation; 5033 995 inputs->GetParameterValue(&approximation,ApproximationEnum); … … 5041 1003 return; //the elements around will create the solution 5042 1004 } 5043 }5044 else if(analysis_type==DiagnosticHutterAnalysisEnum){1005 break; 1006 case DiagnosticHutterAnalysisEnum: 5045 1007 GetSolutionFromInputsDiagnosticHutter(solution); 5046 }5047 else if(analysis_type==DiagnosticVertAnalysisEnum){1008 break; 1009 case DiagnosticVertAnalysisEnum: 5048 1010 GetSolutionFromInputsDiagnosticVert(solution); 5049 } 1011 break; 1012 #endif 5050 1013 #ifdef _HAVE_THERMAL_ 5051 else if(analysis_type==ThermalAnalysisEnum){1014 case ThermalAnalysisEnum: 5052 1015 GetSolutionFromInputsThermal(solution); 5053 }5054 else if(analysis_type==EnthalpyAnalysisEnum){1016 break; 1017 case EnthalpyAnalysisEnum: 5055 1018 GetSolutionFromInputsEnthalpy(solution); 5056 }1019 break; 5057 1020 #endif 5058 else{1021 default: 5059 1022 _error_("analysis: %i (%s) not supported yet",analysis_type,EnumToStringx(analysis_type)); 5060 1023 } 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 elements5081 * (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);5217 1024 } 5218 1025 /*}}}*/ … … 5851 1658 5852 1659 /*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: 5854 1663 InputUpdateFromSolutionDiagnosticHoriz( solution); 5855 }5856 else if (analysis_type==DiagnosticHutterAnalysisEnum){1664 break; 1665 case DiagnosticHutterAnalysisEnum: 5857 1666 InputUpdateFromSolutionDiagnosticHutter( solution); 5858 }5859 else if (analysis_type==DiagnosticVertAnalysisEnum){1667 break; 1668 case DiagnosticVertAnalysisEnum: 5860 1669 InputUpdateFromSolutionDiagnosticVert( solution); 5861 } 1670 break; 1671 #endif 5862 1672 #ifdef _HAVE_CONTROL_ 5863 else if (analysis_type==AdjointHorizAnalysisEnum){1673 case AdjointHorizAnalysisEnum: 5864 1674 int approximation; 5865 1675 inputs->GetParameterValue(&approximation,ApproximationEnum); … … 5870 1680 InputUpdateFromSolutionAdjointHoriz( solution); 5871 1681 } 5872 }1682 break; 5873 1683 #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: 5875 1696 InputUpdateFromSolutionOneDofCollapsed(solution,BedSlopeXEnum); 5876 }5877 else if (analysis_type==BedSlopeYAnalysisEnum){1697 break; 1698 case BedSlopeYAnalysisEnum: 5878 1699 InputUpdateFromSolutionOneDofCollapsed(solution,BedSlopeYEnum); 5879 }5880 else if (analysis_type==SurfaceSlopeXAnalysisEnum){1700 break; 1701 case SurfaceSlopeXAnalysisEnum: 5881 1702 InputUpdateFromSolutionOneDofCollapsed(solution,SurfaceSlopeXEnum); 5882 }5883 else if (analysis_type==SurfaceSlopeYAnalysisEnum){1703 break; 1704 case SurfaceSlopeYAnalysisEnum: 5884 1705 InputUpdateFromSolutionOneDofCollapsed(solution,SurfaceSlopeYEnum); 5885 }5886 else if (analysis_type==PrognosticAnalysisEnum){1706 break; 1707 case PrognosticAnalysisEnum: 5887 1708 InputUpdateFromSolutionPrognostic(solution); 5888 } 5889 else if (analysis_type==BalancethicknessAnalysisEnum){ 1709 break; 1710 #ifdef _HAVE_BALANCED_ 1711 case BalancethicknessAnalysisEnum: 5890 1712 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; 5902 1714 #endif 5903 else{1715 default: 5904 1716 _error_("analysis %i (%s) not supported yet",analysis_type,EnumToStringx(analysis_type)); 5905 1717 } 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 old6007 * 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 pattyn6052 * 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 old6106 * 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 macayeal6147 * 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 old6201 * 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 old6276 * 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 pattyn6315 * 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 old6364 * 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 old6444 * 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 old6561 * 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 old6623 * 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);6638 1718 } 6639 1719 /*}}}*/ … … 7738 2818 } 7739 2819 /*}}}*/ 2820 2821 #ifdef _HAVE_THERMAL_ 2822 /*FUNCTION Penta::CreateKMatrixEnthalpy {{{1*/ 2823 ElementMatrix* 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*/ 2837 ElementMatrix* 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*/ 3000 ElementMatrix* 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*/ 3054 ElementMatrix* 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*/ 3066 ElementMatrix* 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*/ 3080 ElementMatrix* 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*/ 3234 ElementMatrix* 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*/ 3289 ElementVector* 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*/ 3305 ElementVector* 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*/ 3391 ElementVector* 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*/ 3448 ElementVector* 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*/ 3515 ElementVector* Penta::CreatePVectorMelting(void){ 3516 return NULL; 3517 } 3518 /*}}}*/ 3519 /*FUNCTION Penta::CreatePVectorThermal {{{1*/ 3520 ElementVector* 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*/ 3536 ElementVector* 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*/ 3622 ElementVector* 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*/ 3679 ElementVector* 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*/ 3746 void 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*/ 3777 void 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*/ 3808 void 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*/ 3875 void 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*/ 3953 void 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*/ 3973 void 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*/ 3989 void 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*/ 4012 ElementVector* 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*/ 4032 ElementVector* 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*/ 4046 ElementVector* 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*/ 4060 ElementVector* 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*/ 4074 void 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*/ 4165 void 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*/ 4177 void 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*/ 4248 void 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*/ 4340 void 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*/ 4358 void 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*/ 4375 void 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*/ 4392 void 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*/ 4425 cleanup_and_return: 4426 xfree((void**)&control_type); 4427 } 4428 /*}}}*/ 4429 /*FUNCTION Penta::InputUpdateFromSolutionAdjointStokes {{{1*/ 4430 void 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*/ 4473 void 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*/ 4508 double 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*/ 4545 double 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*/ 4582 double 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*/ 4619 double 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*/ 4658 double 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*/ 4695 double Penta::ThicknessAbsGradient(bool process_units,int weight_index){ 4696 4697 _error_("Not implemented yet"); 4698 } 4699 /*}}}*/ 4700 /*FUNCTION Penta::ThicknessAbsMisfit {{{1*/ 4701 double 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*/ 4721 double 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*/ 4736 double 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*/ 4755 void 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*/ 4857 void 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*/ 4862 void 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*/ 4870 ElementVector* 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*/ 4884 ElementVector* 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*/ 4909 ElementMatrix* 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*/ 4923 ElementMatrix* 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*/ 5002 ElementMatrix* 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*/ 5086 ElementMatrix* 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*/ 5100 ElementMatrix* 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*/ 5190 ElementMatrix* 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*/ 5292 ElementMatrix* 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*/ 5325 ElementMatrix* 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*/ 5353 ElementMatrix* 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*/ 5416 ElementMatrix* 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*/ 5439 ElementMatrix* 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*/ 5453 ElementMatrix* 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*/ 5538 ElementMatrix* 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*/ 5555 ElementMatrix* 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*/ 5571 ElementMatrix* 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*/ 5587 ElementMatrix* 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*/ 5602 ElementMatrix* 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*/ 5664 ElementMatrix* 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*/ 5736 ElementMatrix* 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*/ 5752 ElementMatrix* 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*/ 5766 ElementMatrix* 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*/ 5827 ElementMatrix* 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*/ 5912 ElementMatrix* 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*/ 5927 ElementMatrix* 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*/ 5971 ElementMatrix* 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*/ 6018 ElementVector* 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*/ 6032 ElementVector* 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*/ 6091 ElementVector* 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*/ 6163 ElementVector* 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*/ 6177 ElementVector* 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*/ 6236 ElementVector* 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*/ 6308 ElementVector* 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*/ 6336 ElementVector* 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*/ 6350 ElementVector* 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*/ 6366 ElementVector* 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*/ 6382 ElementVector* 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*/ 6470 ElementVector* 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*/ 6484 ElementVector* 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*/ 6529 ElementVector* 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*/ 6543 ElementVector* 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*/ 6622 ElementVector* 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*/ 6687 ElementVector* 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*/ 6701 ElementVector* 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*/ 6757 ElementVector* 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*/ 6822 void 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*/ 6864 void 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*/ 6900 void 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*/ 6933 void 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*/ 6978 void 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*/ 7014 void 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*/ 7099 void 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*/ 7192 void 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*/ 7290 void 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*/ 7361 void 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*/ 7453 void 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*/ 7529 void 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*/ 7652 void 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*/ 7713 ElementMatrix* 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*/ 7738 ElementVector* 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 89 89 double GetZcoord(GaussPenta* gauss); 90 90 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 113 92 int Sid(); 114 93 void InputArtificialNoise(int enum_type,double min, double max); … … 152 131 void ViscousHeatingCreateInput(void); 153 132 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 154 156 /*}}}*/ 155 157 /*Penta specific routines:{{{1*/ 156 158 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_ 158 197 ElementMatrix* CreateKMatrixCouplingMacAyealPattyn(void); 159 198 ElementMatrix* CreateKMatrixCouplingMacAyealPattynViscous(void); … … 183 222 ElementMatrix* CreateKMatrixDiagnosticVertVolume(void); 184 223 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); 198 237 ElementVector* CreatePVectorCouplingMacAyealStokes(void); 199 238 ElementVector* CreatePVectorCouplingMacAyealStokesViscous(void); … … 212 251 ElementVector* CreatePVectorDiagnosticStokesViscous(void); 213 252 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); 214 278 ElementVector* CreatePVectorEnthalpy(void); 215 279 ElementVector* CreatePVectorEnthalpyVolume(void); 216 280 ElementVector* CreatePVectorEnthalpyShelf(void); 217 281 ElementVector* CreatePVectorEnthalpySheet(void); 218 ElementVector* CreatePVectorAdjointStokes(void);219 ElementVector* CreatePVectorDiagnosticVert(void);220 ElementVector* CreatePVectorDiagnosticVertVolume(void);221 ElementVector* CreatePVectorDiagnosticVertBase(void);222 282 ElementVector* CreatePVectorMelting(void); 223 ElementVector* CreatePVectorPrognostic(void);224 ElementVector* CreatePVectorSlope(void);225 283 ElementVector* CreatePVectorThermal(void); 226 284 ElementVector* CreatePVectorThermalVolume(void); 227 285 ElementVector* CreatePVectorThermalShelf(void); 228 286 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 279 295 /*}}}*/ 280 296 }; -
issm/trunk/src/c/objects/Elements/Tria.cpp
r9761 r9775 376 376 } 377 377 /*}}}*/ 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 /*}}}*/424 378 /*FUNCTION Tria::CreateKMatrix {{{1*/ 425 379 void Tria::CreateKMatrix(Mat Kff, Mat Kfs,Vec df){ … … 439 393 /*Just branch to the correct element stiffness matrix generator, according to the type of analysis we are carrying out: */ 440 394 switch(analysis_type){ 395 #ifdef _HAVE_DIAGNOSTIC_ 441 396 case DiagnosticHorizAnalysisEnum: case AdjointHorizAnalysisEnum: 442 397 Ke=CreateKMatrixDiagnosticMacAyeal(); … … 445 400 Ke=CreateKMatrixDiagnosticHutter(); 446 401 break; 402 #endif 447 403 case BedSlopeXAnalysisEnum: case SurfaceSlopeXAnalysisEnum: case BedSlopeYAnalysisEnum: case SurfaceSlopeYAnalysisEnum: 448 404 Ke=CreateKMatrixSlope(); … … 451 407 Ke=CreateKMatrixPrognostic(); 452 408 break; 409 #ifdef _HAVE_HYDROLOGY_ 453 410 case HydrologyAnalysisEnum: 454 411 Ke=CreateKMatrixHydrology(); 455 412 break; 413 #endif 414 #ifdef _HAVE_BALANCED_ 456 415 case BalancethicknessAnalysisEnum: 457 416 Ke=CreateKMatrixBalancethickness(); 458 417 break; 418 #endif 419 #ifdef _HAVE_CONTROL_ 459 420 case AdjointBalancethicknessAnalysisEnum: 460 421 Ke=CreateKMatrixAdjointBalancethickness(); 461 422 break; 423 #endif 462 424 default: 463 425 _error_("analysis %i (%s) not supported yet",analysis_type,EnumToStringx(analysis_type)); … … 469 431 delete Ke; 470 432 } 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;941 433 } 942 434 /*}}}*/ … … 1247 739 /*Just branch to the correct load generator, according to the type of analysis we are carrying out: */ 1248 740 switch(analysis_type){ 741 #ifdef _HAVE_DIAGNOSTIC_ 1249 742 case DiagnosticHorizAnalysisEnum: 1250 743 pe=CreatePVectorDiagnosticMacAyeal(); … … 1253 746 pe=CreatePVectorDiagnosticHutter(); 1254 747 break; 748 #endif 1255 749 case BedSlopeXAnalysisEnum: case SurfaceSlopeXAnalysisEnum: case BedSlopeYAnalysisEnum: case SurfaceSlopeYAnalysisEnum: 1256 750 pe=CreatePVectorSlope(); … … 1259 753 pe=CreatePVectorPrognostic(); 1260 754 break; 755 #ifdef _HAVE_HYDROLOGY_ 1261 756 case HydrologyAnalysisEnum: 1262 757 pe=CreatePVectorHydrology(); 1263 758 break; 759 #endif 760 #ifdef _HAVE_BALANCED_ 1264 761 case BalancethicknessAnalysisEnum: 1265 762 pe=CreatePVectorBalancethickness(); 1266 763 break; 764 #endif 1267 765 #ifdef _HAVE_CONTROL_ 1268 766 case AdjointBalancethicknessAnalysisEnum: … … 1284 782 } 1285 783 /*}}}*/ 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 /*}}}*/1487 784 /*FUNCTION Tria::CreatePVectorPrognostic{{{1*/ 1488 785 ElementVector* Tria::CreatePVectorPrognostic(void){ … … 1496 793 _error_("Element type %s not supported yet",EnumToStringx(GetElementType())); 1497 794 } 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;1544 795 } 1545 796 /*}}}*/ … … 1993 1244 1994 1245 /*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*/ 1267 void 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*/ 1289 void 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*/ 1308 int Tria::Id(){ 1309 1310 return id; 1311 1312 } 1313 /*}}}*/ 1314 /*FUNCTION Tria::Sid {{{1*/ 1315 int Tria::Sid(){ 1316 1317 return sid; 1318 1319 } 1320 /*}}}*/ 1321 /*FUNCTION Tria::InputArtificialNoise{{{1*/ 1322 void 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*/ 1335 bool 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*/ 1365 void 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); 2001 1376 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*/ 1394 void 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*/ 1402 void 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*/ 1415 void 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*/ 1434 void 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*/ 1443 void 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*/ 1452 void 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*/ 1461 void 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*/ 1547 void 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*/ 1602 void 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*/ 1626 void 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*/ 1697 void 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*/ 1729 void 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*/ 1734 void 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*/ 1739 void 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*/ 1758 void 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*/ 1848 bool 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*/ 1873 bool Tria::IsOnBed(){ 1874 1875 bool onbed; 1876 inputs->GetParameterValue(&onbed,MeshElementonbedEnum); 1877 return onbed; 1878 } 1879 /*}}}*/ 1880 /*FUNCTION Tria::IsOnShelf {{{1*/ 1881 bool Tria::IsOnShelf(){ 1882 1883 bool shelf; 1884 inputs->GetParameterValue(&shelf,MaskElementonfloatingiceEnum); 1885 return shelf; 1886 } 1887 /*}}}*/ 1888 /*FUNCTION Tria::IsNodeOnShelf {{{1*/ 1889 bool 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*/ 1904 bool 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*/ 1919 bool Tria::IsOnWater(){ 1920 1921 bool water; 1922 inputs->GetParameterValue(&water,MaskElementonwaterEnum); 1923 return water; 1924 } 1925 /*}}}*/ 1926 /*FUNCTION Tria::MassFlux {{{1*/ 1927 double 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*/ 1990 void 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*/ 2003 void 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*/ 2016 void 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*/ 2029 void 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*/ 2042 void 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*/ 2055 void 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*/ 2069 void 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*/ 2082 void 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*/ 2157 void 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*/ 2170 void 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*/ 2183 void 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*/ 2196 void 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*/ 2209 int Tria::MyRank(void){ 2210 extern int my_rank; 2211 return my_rank; 2212 } 2213 /*}}}*/ 2214 /*FUNCTION Tria::NodalValue {{{1*/ 2215 int 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*/ 2246 void 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*/ 2273 void 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*/ 2297 void 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*/ 2338 void 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*/ 2349 double Tria::RheologyBbarx(void){ 2350 2351 return this->matice->GetBbar(); 2352 2353 } 2354 /*}}}*/ 2355 /*FUNCTION Tria::RequestedOutput{{{1*/ 2356 void 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*/ 2374 void Tria::SetClone(int* minranks){ 2375 2376 _error_("not implemented yet"); 2377 } 2378 /*}}}1*/ 2379 /*FUNCTION Tria::SetCurrentConfiguration {{{1*/ 2380 void 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*/ 2396 void 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*/ 2466 void 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*/ 2530 double 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*/ 2559 void 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*/ 2583 double 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*/ 2625 void 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*/ 2731 int 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*/ 2807 void 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*/ 2830 int 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*/ 2851 ElementMatrix* 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*/ 2865 ElementMatrix* 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*/ 2926 ElementMatrix* 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*/ 2992 ElementMatrix* 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*/ 3013 ElementVector* 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*/ 3064 ElementVector* 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; 2004 3111 } 2005 3112 /*}}}*/ … … 2082 3189 } 2083 3190 /*}}}*/ 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*/ 3192 void 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 2095 3208 /*Get dof list: */ 2096 3209 GetDofList(&doflist,NoneApproximationEnum,GsetEnum); 2097 3210 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: */ 2104 3215 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)); 2114 3246 2115 3247 /*Free ressources:*/ 2116 delete gauss;2117 3248 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*/ 3253 void Tria::InputUpdateFromSolutionDiagnosticHutter(double* solution){ 2163 3254 2164 return id; 2165 2166 } 2167 /*}}}*/ 2168 /*FUNCTION Tria::Sid {{{1*/ 2169 int Tria::Sid(){ 3255 const int numdof=NDOF2*NUMVERTICES; 2170 3256 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 2188 3328 2189 3329 #ifdef _HAVE_CONTROL_ … … 3586 4726 } 3587 4727 /*}}}*/ 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*/ 4729 ElementMatrix* 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(); 3813 4737 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(); 3845 4740 break; 3846 4741 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*/ 4751 void Tria::InputUpdateFromSolutionAdjointHoriz(double* solution){ 4752 3854 4753 const int numdof=NDOF2*NUMVERTICES; 3855 4754 3856 4755 int i; 3857 int dummy;3858 4756 int* doflist=NULL; 3859 double rho_ice,g;3860 4757 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 3868 4761 /*Get dof list: */ 3869 4762 GetDofList(&doflist,NoneApproximationEnum,GsetEnum); … … 3874 4767 /*Ok, we have vx and vy in values, fill in vx and vy arrays: */ 3875 4768 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]; 3878 4771 3879 4772 /*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 } 3900 4776 3901 4777 /*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)); 3906 4780 3907 4781 /*Free ressources:*/ 3908 4782 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*/ 4786 void Tria::InputUpdateFromSolutionAdjointBalancethickness(double* solution){ 4787 4788 const int numdof=NDOF1*NUMVERTICES; 4789 3917 4790 int i; 3918 int dummy;3919 4791 int* doflist=NULL; 3920 double rho_ice,g;3921 4792 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 3931 4795 /*Get dof list: */ 3932 4796 GetDofList(&doflist,NoneApproximationEnum,GsetEnum); … … 3936 4800 3937 4801 /*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 } 3975 4806 3976 4807 /*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)); 3981 4809 3982 4810 /*Free ressources:*/ … … 3984 4812 } 3985 4813 /*}}}*/ 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*/ 4818 void 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*/ 4864 ElementMatrix* 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*/ 4967 ElementVector* 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*/ 5013 void 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; 3993 5022 3994 5023 /*Get dof list: */ 3995 5024 GetDofList(&doflist,NoneApproximationEnum,GsetEnum); 3996 5025 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); 4005 5042 4006 5043 /*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; 4078 5045 xfree((void**)&doflist); 4079 5046 } … … 4107 5074 } 4108 5075 /*}}}*/ 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 4152 5077 4153 5078 #ifdef _HAVE_DAKOTA_ … … 4265 5190 /*}}}*/ 4266 5191 #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*/ 5195 ElementMatrix* 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*/ 5209 ElementMatrix* 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*/ 5324 ElementMatrix* Tria::CreateKMatrixBalancethickness_DG(void){ 5325 5326 /*Constants*/ 5327 const int numdof=NDOF1*NUMVERTICES; 4288 5328 4289 5329 /*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; 4462 5332 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*/ 4480 5343 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); 4494 5345 Input* vx_input=inputs->GetInput(VxEnum); _assert_(vx_input); 4495 5346 Input* vy_input=inputs->GetInput(VyEnum); _assert_(vy_input); 4496 5347 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*/ 5378 ElementVector* 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*/ 5392 ElementVector* Tria::CreatePVectorBalancethickness_CG(void){ 5393 5394 /*Constants*/ 5395 const int numdof=NDOF1*NUMVERTICES; 4678 5396 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); 4910 5412 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*/ 5435 ElementVector* 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*/ 5070 5451 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 89 89 void GetSolutionFromInputs(Vec solution); 90 90 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 116 92 void InputArtificialNoise(int enum_type,double min, double max); 117 93 bool InputConvergence(double* eps, int* enums,int num_enums,int* criterionenums,double* criterionvalues,int num_criterionenums); … … 121 97 void InputDuplicate(int original_enum,int new_enum); 122 98 void InputScale(int enum_type,double scale_factor); 123 99 void InputToResult(int enum_type,int step,double time); 124 100 void DeleteResults(void); 125 101 void MaterialUpdateFromTemperature(void){_error_("not implemented yet");}; … … 154 130 double RheologyBbarx(void); 155 131 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 156 159 /*}}}*/ 157 160 /*Tria specific routines:{{{1*/ 158 ElementMatrix* CreateKMatrixAdjointBalancethickness(void);159 161 ElementMatrix* CreateKMatrixBalancethickness(void); 160 162 ElementMatrix* CreateKMatrixBalancethickness_DG(void); 161 163 ElementMatrix* CreateKMatrixBalancethickness_CG(void); 162 ElementMatrix* CreateKMatrixDiagnosticMacAyeal(void);163 ElementMatrix* CreateKMatrixDiagnosticMacAyealViscous(void);164 ElementMatrix* CreateKMatrixDiagnosticMacAyealFriction(void);165 ElementMatrix* CreateKMatrixDiagnosticHutter(void);166 164 ElementMatrix* CreateKMatrixMelting(void); 167 ElementMatrix* CreateKMatrixHydrology(void);168 165 ElementMatrix* CreateKMatrixPrognostic(void); 169 166 ElementMatrix* CreateKMatrixPrognostic_CG(void); … … 173 170 ElementVector* CreatePVectorBalancethickness_DG(void); 174 171 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);181 172 ElementVector* CreatePVectorPrognostic(void); 182 173 ElementVector* CreatePVectorPrognostic_CG(void); 183 174 ElementVector* CreatePVectorPrognostic_DG(void); 184 175 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); 195 200 void GetSolutionFromInputsDiagnosticHoriz(Vec solution); 196 201 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); 199 211 void InputUpdateFromSolutionAdjointBalancethickness( double* solution); 200 212 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); 205 220 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 209 225 /*}}}*/ 210 226 -
issm/trunk/src/c/objects/Loads/Icefront.cpp
r9725 r9775 436 436 case MacAyeal2dIceFrontEnum: 437 437 return CreatePVectorDiagnosticMacAyeal2d(); 438 #ifdef _HAVE_THREED_ 438 439 case MacAyeal3dIceFrontEnum: 439 440 return CreatePVectorDiagnosticMacAyeal3d(); … … 442 443 case StokesIceFrontEnum: 443 444 return CreatePVectorDiagnosticStokes(); 445 #endif 444 446 default: 445 447 _error_("Icefront type %s not supported yet",EnumToStringx(type)); … … 532 534 } 533 535 /*}}}*/ 536 #ifdef _HAVE_THREED_ 534 537 /*FUNCTION Icefront::CreatePVectorDiagnosticMacAyeal3d{{{1*/ 535 538 ElementVector* Icefront::CreatePVectorDiagnosticMacAyeal3d(void){ … … 709 712 } 710 713 /*}}}*/ 714 #endif 711 715 /*FUNCTION Icefront::GetDofList {{{1*/ 712 716 void Icefront::GetDofList(int** pdoflist,int approximation_enum,int setenum){ -
issm/trunk/src/c/objects/Loads/Icefront.h
r8800 r9775 81 81 ElementVector* CreatePVectorDiagnosticHoriz(void); 82 82 ElementVector* CreatePVectorDiagnosticMacAyeal2d(void); 83 #ifdef _HAVE_THREED_ 83 84 ElementVector* CreatePVectorDiagnosticMacAyeal3d(void); 84 85 ElementVector* CreatePVectorDiagnosticPattyn(void); 85 86 ElementVector* CreatePVectorDiagnosticStokes(void); 87 #endif 86 88 void GetDofList(int** pdoflist,int approximation_enum,int setenum); 87 89 void GetSegmentNormal(double* normal,double xyz_list[2][3]); -
issm/trunk/src/c/objects/Loads/Riftfront.cpp
r9725 r9775 851 851 } 852 852 /*}}}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 indexed861 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*/867 853 /*FUNCTION Riftfront::Penetration {{{1*/ 868 854 int Riftfront::Penetration(double* ppenetration){ -
issm/trunk/src/c/objects/Loads/Riftfront.h
r8800 r9775 98 98 int PotentialUnstableConstraint(int* punstable); 99 99 int IsMaterialStable(void); 100 void OutputProperties(Vec riftproperties);101 100 bool IsInput(int name); 102 101 /*}}}*/ -
issm/trunk/src/c/objects/Materials/Matice.cpp
r9761 r9775 706 706 707 707 /*if 3d*/ 708 #ifdef _HAVE_THREED_ 708 709 else if(dim==3){ 709 710 … … 745 746 #endif 746 747 } 748 #endif 747 749 else{ 748 750 _error_(" Mesh type not supported yet!"); -
issm/trunk/src/c/solutions/CorePointerFromSolutionEnum.cpp
r9761 r9775 26 26 27 27 case DiagnosticSolutionEnum: 28 #ifdef _HAVE_DIAGNOSTIC_ 28 29 solutioncore=&diagnostic_core; 30 #else 31 _error_("ISSM was not compiled with diagnostic capabilities. Exiting"); 32 #endif 29 33 break; 30 34 case SteadystateSolutionEnum: 35 #ifdef _HAVE_STEADYSTATE_ 31 36 solutioncore=&steadystate_core; 37 _error_("ISSM was not compiled with steady state capabilities. Exiting"); 38 #endif 32 39 break; 33 40 case ThermalSolutionEnum: … … 45 52 #endif 46 53 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 49 60 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 52 67 break; 53 68 case SurfaceSlopeSolutionEnum: 69 #ifdef _HAVE_SLOPE_ 54 70 solutioncore=&surfaceslope_core; 71 #else 72 _error_("ISSM was not compiled with slope capabilities. Exiting"); 73 #endif 55 74 break; 56 75 case BedSlopeSolutionEnum: 76 #ifdef _HAVE_SLOPE_ 57 77 solutioncore=&bedslope_core; 78 #else 79 _error_("ISSM was not compiled with slope capabilities. Exiting"); 80 #endif 58 81 break; 59 82 case TransientSolutionEnum: 83 #ifdef _HAVE_TRANSIENT_ 60 84 solutioncore=&transient_core; 85 #else 86 _error_("ISSM was not compiled with transient capabilities. Exiting"); 87 #endif 61 88 break; 62 89 case GroundinglineMigration2dSolutionEnum: 90 #ifdef _HAVE_GROUNDINGLINE_ 63 91 solutioncore=&groundinglinemigration2d_core; 92 #else 93 _error_("ISSM was not compiled with grounding line migration capabilities. Exiting"); 94 #endif 64 95 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 67 102 break; 68 103 default: -
issm/trunk/src/c/solutions/transient_core.cpp
r9761 r9775 81 81 if(isdiagnostic){ 82 82 _printf_(VerboseSolution()," computing new velocity\n"); 83 #ifdef _HAVE_DIAGNOSTIC_ 83 84 diagnostic_core(femmodel); 85 #else 86 _error_("ISSM was not compiled with diagnostic capabilities. Exiting"); 87 #endif 88 84 89 } 85 90 … … 94 99 if(dim==3) _error_("Grounding line migration not implemented in 3d"); 95 100 _printf_(VerboseSolution()," computing new grounding line position\n"); 101 #ifdef _HAVE_DIAGNOSTIC_ 96 102 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 97 107 } 98 108 -
issm/trunk/src/mex/Makefile.am
r9570 r9775 54 54 NodesDof\ 55 55 Orth\ 56 OutputRifts\57 56 OutputResults\ 58 57 ParsePetscOptions\ … … 261 260 Orth/Orth.h 262 261 263 OutputRifts_SOURCES = OutputRifts/OutputRifts.cpp\264 OutputRifts/OutputRifts.h265 266 262 OutputResults_SOURCES = OutputResults/OutputResults.cpp\ 267 263 OutputResults/OutputResults.h
Note:
See TracChangeset
for help on using the changeset viewer.