Changeset 4885
- Timestamp:
- 07/29/10 14:40:49 (15 years ago)
- Location:
- issm/trunk/src/c
- Files:
-
- 14 edited
Legend:
- Unmodified
- Added
- Removed
-
issm/trunk/src/c/EnumDefinitions/EnumAsString.cpp
r4873 r4885 225 225 case P1Enum : return "P1"; 226 226 case P1DGEnum : return "P1DG"; 227 case MiniEnum : return "Mini"; 227 228 case DoubleElementResultEnum : return "DoubleElementResult"; 228 229 case TriaVertexElementResultEnum : return "TriaVertexElementResult"; -
issm/trunk/src/c/EnumDefinitions/EnumDefinitions.h
r4873 r4885 254 254 P1Enum, 255 255 P1DGEnum, 256 MiniEnum, 256 257 /*}}}*/ 257 258 /*Results{{{1*/ -
issm/trunk/src/c/EnumDefinitions/StringAsEnum.cpp
r4873 r4885 223 223 else if (strcmp(name,"P1")==0) return P1Enum; 224 224 else if (strcmp(name,"P1DG")==0) return P1DGEnum; 225 else if (strcmp(name,"Mini")==0) return MiniEnum; 225 226 else if (strcmp(name,"DoubleElementResult")==0) return DoubleElementResultEnum; 226 227 else if (strcmp(name,"TriaVertexElementResult")==0) return TriaVertexElementResultEnum; -
issm/trunk/src/c/objects/Elements/Penta.cpp
r4882 r4885 88 88 89 89 penta=new Penta(); 90 91 //deal with PentaRef mother class 92 penta->element_type_list=(int*)xmalloc(this->numanalyses*sizeof(int)); 93 for(i=0;i<this->numanalyses;i++) penta->element_type_list[i]=this->element_type_list[i]; 90 94 91 95 //deal with PentaHook mother class … … 161 165 /*this time, no need to get enum type, the pointer directly points to the beginning of the 162 166 *object data (thanks to DataSet::Demarshall):*/ 163 164 167 memcpy(&id,marshalled_dataset,sizeof(id));marshalled_dataset+=sizeof(id); 165 168 memcpy(&numanalyses,marshalled_dataset,sizeof(numanalyses));marshalled_dataset+=sizeof(numanalyses); 169 170 /*demarshall Ref: */ 171 this->element_type_list=(int*)xmalloc(this->numanalyses*sizeof(int)); 172 for(i=0;i<numanalyses;i++){ memcpy(&element_type_list[i],marshalled_dataset,sizeof(int));marshalled_dataset+=sizeof(int);} 166 173 167 174 /*allocate dynamic memory: */ … … 240 247 memcpy(marshalled_dataset,&id,sizeof(id));marshalled_dataset+=sizeof(id); 241 248 memcpy(marshalled_dataset,&numanalyses,sizeof(numanalyses));marshalled_dataset+=sizeof(numanalyses); 249 250 /*Mershall Ref: */ 251 for(i=0;i<numanalyses;i++){ 252 memcpy(marshalled_dataset,&element_type_list[i],sizeof(element_type_list[i]));marshalled_dataset+=sizeof(element_type_list[i]); 253 } 242 254 243 255 /*Marshall hooks: */ … … 293 305 +hnodes_size 294 306 +sizeof(numanalyses) 307 +numanalyses*sizeof(int) //element_type_lists 295 308 +hmatice->MarshallSize() 296 309 +hmatpar->MarshallSize() … … 633 646 parametersin->FindParam(&analysis_counter,AnalysisCounterEnum); 634 647 648 /*Get Element type*/ 649 this->element_type=this->element_type_list[analysis_counter]; 650 635 651 /*Take care of hooking up all objects for this element, ie links the objects in the hooks to their respective 636 652 * datasets, using internal ids and offsets hidden in hooks: */ … … 641 657 642 658 /*Now, go pick up the objects inside the hooks: */ 643 if (this->hnodes[analysis_counter]) this->nodes=(Node**)this->hnodes[analysis_counter]->deliverp();644 else this->nodes=NULL;645 this->matice=(Matice*)this->hmatice->delivers();646 this->matpar=(Matpar*)this->hmatpar->delivers();647 this->neighbors=(Penta**)this->hneighbors->deliverp();648 649 /*point parameters to real dataset: */650 this->parameters=parametersin;651 }652 /*}}}*/653 /*FUNCTION Penta::SetCurrentConfiguration {{{1*/654 void Penta::SetCurrentConfiguration(Elements* elementsin, Loads* loadsin, DataSet* nodesin, Materials* materialsin, Parameters* parametersin){655 656 int analysis_counter;657 658 /*go into parameters and get the analysis_counter: */659 parametersin->FindParam(&analysis_counter,AnalysisCounterEnum);660 661 /*Pick up the objects inside the hooks: */662 659 if (this->hnodes[analysis_counter]) this->nodes=(Node**)this->hnodes[analysis_counter]->deliverp(); 663 660 else this->nodes=NULL; … … 958 955 } 959 956 /*}}}*/ 960 /*FUNCTION Penta::GradjDrag {{{1*/961 void Penta::GradjDrag(Vec gradient){962 963 int i;964 Tria* tria=NULL;965 TriaVertexInput* triavertexinput=NULL;966 double temp_gradient[6]={0,0,0,0,0,0};967 968 /*inputs: */969 bool onwater;970 bool onbed;971 bool shelf;972 int analysis_type;973 974 /*retrieve parameters: */975 parameters->FindParam(&analysis_type,AnalysisTypeEnum);976 977 /*retrieve inputs :*/978 inputs->GetParameterValue(&onwater,ElementOnWaterEnum);979 inputs->GetParameterValue(&onbed,ElementOnBedEnum);980 inputs->GetParameterValue(&shelf,ElementOnIceShelfEnum);981 982 /*If on water, skip: */983 if(onwater)return;984 985 /*If on shelf, skip: */986 if(shelf)return;987 988 /*Bail out if this element does not touch the bedrock: */989 if (!onbed) return;990 991 if (analysis_type==AdjointHorizAnalysisEnum){992 993 /*MacAyeal or Pattyn*/994 tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria.995 tria->GradjDrag(gradient);996 delete tria;997 }998 else if (analysis_type==AdjointStokesAnalysisEnum){999 1000 /*Stokes*/1001 tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria.1002 tria->GradjDragStokes(gradient);1003 delete tria;1004 }1005 else ISSMERROR("analysis %s not supported yet",EnumAsString(analysis_type));1006 1007 1008 }1009 /*}}}*/1010 957 /*FUNCTION Penta::InputAXPY{{{1*/ 1011 958 void Penta::InputAXPY(int YEnum, double scalar, int XEnum){ … … 1692 1639 } 1693 1640 /*}}}*/ 1641 /*FUNCTION Penta::SetCurrentConfiguration {{{1*/ 1642 void Penta::SetCurrentConfiguration(Elements* elementsin, Loads* loadsin, DataSet* nodesin, Materials* materialsin, Parameters* parametersin){ 1643 1644 int analysis_counter; 1645 1646 /*go into parameters and get the analysis_counter: */ 1647 parametersin->FindParam(&analysis_counter,AnalysisCounterEnum); 1648 1649 /*Get Element type*/ 1650 this->element_type=this->element_type_list[analysis_counter]; 1651 1652 /*Pick up the objects inside the hooks: */ 1653 if (this->hnodes[analysis_counter]) this->nodes=(Node**)this->hnodes[analysis_counter]->deliverp(); 1654 else this->nodes=NULL; 1655 this->matice=(Matice*)this->hmatice->delivers(); 1656 this->matpar=(Matpar*)this->hmatpar->delivers(); 1657 this->neighbors=(Penta**)this->hneighbors->deliverp(); 1658 1659 /*point parameters to real dataset: */ 1660 this->parameters=parametersin; 1661 } 1662 /*}}}*/ 1694 1663 /*FUNCTION Penta::SurfaceArea {{{1*/ 1695 1664 double Penta::SurfaceArea(void){ … … 1756 1725 /*P1 Discontinuous Galerkin*/ 1757 1726 penta_type=P1DGEnum; 1727 } 1728 else if (analysis_type==StokesAnalysisEnum){ 1729 /*MINI Continuous Galerkin*/ 1730 penta_type=MiniEnum; 1758 1731 } 1759 1732 else{ … … 1968 1941 1969 1942 /*Penta specific routines: */ 1970 /*FUNCTION Penta::SpawnTria {{{1*/ 1971 Tria* Penta::SpawnTria(int g0, int g1, int g2){ 1943 /*FUNCTION Penta::CreateKMatrixBalancedthickness {{{1*/ 1944 1945 void Penta::CreateKMatrixBalancedthickness(Mat Kgg){ 1946 1947 /*Collapsed formulation: */ 1948 Tria* tria=NULL; 1949 1950 /*flags: */ 1951 bool onwater; 1952 bool onbed; 1953 1954 /*recover some inputs: */ 1955 inputs->GetParameterValue(&onwater,ElementOnWaterEnum); 1956 inputs->GetParameterValue(&onbed,ElementOnBedEnum); 1957 1958 /*If on water, skip: */ 1959 if(onwater)return; 1960 1961 /*Is this element on the bed? :*/ 1962 if(!onbed)return; 1963 1964 /*Spawn Tria element from the base of the Penta: */ 1965 tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria. 1966 tria->CreateKMatrix(Kgg); 1967 delete tria; 1968 return; 1969 1970 } 1971 /*}}}*/ 1972 /*FUNCTION Penta::CreateKMatrixBalancedvelocities {{{1*/ 1973 1974 void Penta::CreateKMatrixBalancedvelocities(Mat Kgg){ 1975 1976 /*Collapsed formulation: */ 1977 Tria* tria=NULL; 1978 1979 /*flags: */ 1980 bool onbed; 1981 bool onwater; 1982 1983 /*recover some inputs: */ 1984 inputs->GetParameterValue(&onbed,ElementOnBedEnum); 1985 inputs->GetParameterValue(&onwater,ElementOnWaterEnum); 1986 1987 /*If on water, skip: */ 1988 if(onwater)return; 1989 1990 /*Is this element on the bed? :*/ 1991 if(!onbed)return; 1992 1993 /*Spawn Tria element from the base of the Penta: */ 1994 tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria. 1995 tria->CreateKMatrix(Kgg); 1996 delete tria; 1997 return; 1998 1999 } 2000 /*}}}*/ 2001 /*FUNCTION Penta::CreateKMatrixDiagnosticHoriz {{{1*/ 2002 void Penta::CreateKMatrixDiagnosticHoriz( Mat Kgg){ 2003 2004 /* local declarations */ 2005 int i,j; 2006 2007 /* node data: */ 2008 const int numgrids=6; 2009 const int numdof=2*numgrids; 2010 double xyz_list[numgrids][3]; 2011 int doflist[numdof]; 2012 int numberofdofspernode; 2013 2014 /* 3d gaussian points: */ 2015 int num_gauss,ig; 2016 double* first_gauss_area_coord = NULL; 2017 double* second_gauss_area_coord = NULL; 2018 double* third_gauss_area_coord = NULL; 2019 double* fourth_gauss_vert_coord = NULL; 2020 double* area_gauss_weights = NULL; 2021 double* vert_gauss_weights = NULL; 2022 int ig1,ig2; 2023 double gauss_weight1,gauss_weight2; 2024 double gauss_coord[4]; 2025 int order_area_gauss; 2026 int num_vert_gauss; 2027 int num_area_gauss; 2028 double gauss_weight; 2029 2030 /* 2d gaussian point: */ 2031 int num_gauss2d; 2032 double* first_gauss_area_coord2d = NULL; 2033 double* second_gauss_area_coord2d = NULL; 2034 double* third_gauss_area_coord2d = NULL; 2035 double* gauss_weights2d=NULL; 2036 double gauss_l1l2l3[3]; 2037 2038 /* material data: */ 2039 double viscosity; //viscosity 2040 double oldviscosity; //viscosity 2041 double newviscosity; //viscosity 2042 2043 /* strain rate: */ 2044 double epsilon[5]; /* epsilon=[exx,eyy,exy,exz,eyz];*/ 2045 double oldepsilon[5]; /* epsilon=[exx,eyy,exy,exz,eyz];*/ 2046 2047 /* matrices: */ 2048 double B[5][numdof]; 2049 double Bprime[5][numdof]; 2050 double L[2][numdof]; 2051 double D[5][5]={0.0}; // material matrix, simple scalar matrix. 2052 double D_scalar; 2053 double DL[2][2]={0.0}; //for basal drag 2054 double DL_scalar; 2055 2056 /* local element matrices: */ 2057 double Ke_gg[numdof][numdof]={0.0}; //local element stiffness matrix 2058 2059 double Ke_gg_gaussian[numdof][numdof]; //stiffness matrix evaluated at the gaussian point. 2060 double Ke_gg_drag_gaussian[numdof][numdof]; //stiffness matrix contribution from drag 2061 double Jdet; 2062 2063 /*slope: */ 2064 double slope[2]={0.0}; 2065 double slope_magnitude; 2066 2067 /*friction: */ 2068 double alpha2_list[3]; 2069 double alpha2; 2070 2071 double MAXSLOPE=.06; // 6 % 2072 double MOUNTAINKEXPONENT=10; 2073 2074 /*parameters: */ 2075 double viscosity_overshoot; 2076 2077 /*Collapsed formulation: */ 2078 Tria* tria=NULL; 2079 2080 /*inputs: */ 2081 bool onwater; 2082 bool collapse; 2083 bool onbed; 2084 bool shelf; 2085 Input* vx_input=NULL; 2086 Input* vy_input=NULL; 2087 Input* vxold_input=NULL; 2088 Input* vyold_input=NULL; 2089 2090 /*retrieve inputs :*/ 2091 inputs->GetParameterValue(&onwater,ElementOnWaterEnum); 2092 inputs->GetParameterValue(&collapse,CollapseEnum); 2093 inputs->GetParameterValue(&onbed,ElementOnBedEnum); 2094 inputs->GetParameterValue(&shelf,ElementOnIceShelfEnum); 2095 2096 /*retrieve some parameters: */ 2097 this->parameters->FindParam(&viscosity_overshoot,ViscosityOvershootEnum); 2098 2099 /*If on water, skip stiffness: */ 2100 if(onwater)return; 2101 2102 /*Figure out if this pentaelem is collapsed. If so, then bailout, except if it is at the 2103 bedrock, in which case we spawn a tria element using the 3 first grids, and use it to build 2104 the stiffness matrix. */ 2105 2106 if ((collapse==1) && (onbed==0)){ 2107 /*This element should be collapsed, but this element is not on the bedrock, therefore all its 2108 * dofs have already been frozen! Do nothing: */ 2109 return; 2110 } 2111 else if ((collapse==1) && (onbed==1)){ 2112 2113 /*This element should be collapsed into a tria element at its base. Create this tria element, 2114 *and use its CreateKMatrix functionality to fill the global stiffness matrix: */ 2115 tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria. 2116 tria->CreateKMatrix(Kgg); 2117 delete tria; 2118 return; 2119 } 2120 else{ 2121 2122 /*Implement standard penta element: */ 2123 2124 /* Get node coordinates and dof list: */ 2125 GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids); 2126 GetDofList(&doflist[0],&numberofdofspernode); 2127 2128 /*Get gaussian points and weights. Penta is an extrusion of a Tria, we therefore 2129 get tria gaussian points as well as segment gaussian points. For tria gaussian 2130 points, order of integration is 2, because we need to integrate the product tB*D*B' 2131 which is a polynomial of degree 3 (see GaussTria for more details). For segment gaussian 2132 points, same deal, which yields 3 gaussian points.*/ 2133 2134 order_area_gauss=5; 2135 num_vert_gauss=5; 2136 2137 GaussPenta( &num_area_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &area_gauss_weights, &fourth_gauss_vert_coord,&vert_gauss_weights,order_area_gauss,num_vert_gauss); 2138 2139 /*Retrieve all inputs we will be needing: */ 2140 vx_input=inputs->GetInput(VxEnum); 2141 vy_input=inputs->GetInput(VyEnum); 2142 vxold_input=inputs->GetInput(VxOldEnum); 2143 vyold_input=inputs->GetInput(VyOldEnum); 2144 2145 /* Start looping on the number of gaussian points: */ 2146 for (ig1=0; ig1<num_area_gauss; ig1++){ 2147 for (ig2=0; ig2<num_vert_gauss; ig2++){ 2148 2149 /*Pick up the gaussian point: */ 2150 gauss_weight1=*(area_gauss_weights+ig1); 2151 gauss_weight2=*(vert_gauss_weights+ig2); 2152 gauss_weight=gauss_weight1*gauss_weight2; 2153 2154 2155 gauss_coord[0]=*(first_gauss_area_coord+ig1); 2156 gauss_coord[1]=*(second_gauss_area_coord+ig1); 2157 gauss_coord[2]=*(third_gauss_area_coord+ig1); 2158 gauss_coord[3]=*(fourth_gauss_vert_coord+ig2); 2159 2160 2161 /*Get strain rate from velocity: */ 2162 this->GetStrainRate3dPattyn(&epsilon[0],&xyz_list[0][0],gauss_coord,vx_input,vy_input); 2163 this->GetStrainRate3dPattyn(&oldepsilon[0],&xyz_list[0][0],gauss_coord,vxold_input,vyold_input); 2164 2165 /*Get viscosity: */ 2166 matice->GetViscosity3d(&viscosity, &epsilon[0]); 2167 matice->GetViscosity3d(&oldviscosity, &oldepsilon[0]); 2168 2169 /*Get B and Bprime matrices: */ 2170 GetBPattyn(&B[0][0], &xyz_list[0][0], gauss_coord); 2171 GetBprimePattyn(&Bprime[0][0], &xyz_list[0][0], gauss_coord); 2172 2173 /* Get Jacobian determinant: */ 2174 GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss_coord); 2175 2176 /*Build the D matrix: we plug the gaussian weight, the viscosity, and the jacobian determinant 2177 onto this scalar matrix, so that we win some computational time: */ 2178 2179 newviscosity=viscosity+viscosity_overshoot*(viscosity-oldviscosity); 2180 D_scalar=newviscosity*gauss_weight*Jdet; 2181 for (i=0;i<5;i++){ 2182 D[i][i]=D_scalar; 2183 } 2184 2185 /* Do the triple product tB*D*Bprime: */ 2186 TripleMultiply( &B[0][0],5,numdof,1, 2187 &D[0][0],5,5,0, 2188 &Bprime[0][0],5,numdof,0, 2189 &Ke_gg_gaussian[0][0],0); 2190 2191 /* Add the Ke_gg_gaussian, and optionally Ke_gg_gaussian onto Ke_gg: */ 2192 for( i=0; i<numdof; i++){ 2193 for(j=0;j<numdof;j++){ 2194 Ke_gg[i][j]+=Ke_gg_gaussian[i][j]; 2195 } 2196 } 2197 } //for (ig2=0; ig2<num_vert_gauss; ig2++) 2198 } //for (ig1=0; ig1<num_area_gauss; ig1++) 2199 2200 2201 /*Add Ke_gg to global matrix Kgg: */ 2202 MatSetValues(Kgg,numdof,doflist,numdof,doflist,(const double*)Ke_gg,ADD_VALUES); 2203 2204 //Deal with 2d friction at the bedrock interface 2205 if((onbed && !shelf)){ 2206 2207 /*Build a tria element using the 3 grids of the base of the penta. Then use 2208 * the tria functionality to build a friction stiffness matrix on these 3 2209 * grids: */ 2210 2211 tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria. 2212 tria->CreateKMatrixDiagnosticHorizFriction(Kgg); 2213 delete tria; 2214 } 2215 2216 } 2217 2218 xfree((void**)&first_gauss_area_coord); 2219 xfree((void**)&second_gauss_area_coord); 2220 xfree((void**)&third_gauss_area_coord); 2221 xfree((void**)&fourth_gauss_vert_coord); 2222 xfree((void**)&area_gauss_weights); 2223 xfree((void**)&vert_gauss_weights); 2224 xfree((void**)&first_gauss_area_coord2d); 2225 xfree((void**)&second_gauss_area_coord2d); 2226 xfree((void**)&third_gauss_area_coord2d); 2227 xfree((void**)&gauss_weights2d); 2228 2229 } 2230 /*}}}*/ 2231 /*FUNCTION Penta::CreateKMatrixDiagnosticHutter{{{1*/ 2232 void Penta::CreateKMatrixDiagnosticHutter(Mat Kgg){ 2233 2234 /*Collapsed formulation: */ 2235 Beam* beam=NULL; 2236 int i; 2237 2238 /*flags: */ 2239 bool onwater; 2240 2241 /*recover some inputs: */ 2242 inputs->GetParameterValue(&onwater,ElementOnWaterEnum); 2243 2244 /*If on water, skip: */ 2245 if(onwater)return; 2246 2247 /*Spawn 3 beam elements: */ 2248 for(i=0;i<3;i++){ 2249 beam=(Beam*)SpawnBeam(i,i+3); //[0 3], [1 4] and [2 5] are the four vertical edges of the Penta 2250 beam->CreateKMatrix(Kgg); 2251 } 2252 2253 /*clean up*/ 2254 delete beam; 2255 2256 } 2257 /*}}}*/ 2258 /*FUNCTION Penta::CreateKMatrixDiagnosticStokes {{{1*/ 2259 void Penta::CreateKMatrixDiagnosticStokes( Mat Kgg){ 2260 2261 int i,j; 2262 2263 const int numgrids=6; 2264 const int DOFPERGRID=4; 2265 const int numdof=numgrids*DOFPERGRID; 2266 int doflist[numdof]; 2267 int numberofdofspernode; 2268 2269 const int numgrids2d=3; 2270 const int numdof2d=numgrids2d*DOFPERGRID; 2271 2272 int dofs[3]={0,1,2}; 2273 2274 double K_terms[numdof][numdof]={0.0}; 2275 2276 /*Material properties: */ 2277 double gravity,rho_ice,rho_water; 2278 2279 /*Collapsed formulation: */ 2280 Tria* tria=NULL; 2281 2282 /*Grid data: */ 2283 double xyz_list[numgrids][3]; 2284 2285 /*parameters: */ 2286 double xyz_list_tria[numgrids2d][3]; 2287 double surface_normal[3]; 2288 double bed_normal[3]; 2289 double thickness; 2290 2291 /*matrices: */ 2292 double Ke_temp[27][27]={0.0}; //for the six nodes and the bubble 2293 double Ke_reduced[numdof][numdof]; //for the six nodes only 2294 double Ke_gaussian[27][27]; 2295 double Ke_drag_gaussian[numdof2d][numdof2d]; 2296 double B[8][27]; 2297 double B_prime[8][27]; 2298 double LStokes[14][numdof2d]; 2299 double LprimeStokes[14][numdof2d]; 2300 double Jdet; 2301 double Jdet2d; 2302 double D[8][8]={0.0}; 2303 double D_scalar; 2304 double tBD[27][8]; 2305 double DLStokes[14][14]={0.0}; 2306 double tLDStokes[numdof2d][14]; 2307 2308 /* gaussian points: */ 2309 int num_area_gauss; 2310 int igarea,igvert; 2311 double* first_gauss_area_coord = NULL; 2312 double* second_gauss_area_coord = NULL; 2313 double* third_gauss_area_coord = NULL; 2314 double* vert_gauss_coord = NULL; 2315 double* area_gauss_weights = NULL; 2316 double* vert_gauss_weights = NULL; 2317 double gaussgrids[numgrids][4]={{1,0,0,-1},{0,1,0,-1},{0,0,1,-1},{1,0,0,1},{0,1,0,1},{0,0,1,1}}; 2318 2319 /* specific gaussian point: */ 2320 double gauss_weight,area_gauss_weight,vert_gauss_weight; 2321 double gauss_coord[4]; 2322 double gauss_coord_tria[3]; 2323 int area_order=5; 2324 int num_vert_gauss=5; 2325 2326 double epsilon[6]; /* epsilon=[exx,eyy,ezz,exy,exz,eyz];*/ 2327 double viscosity; 2328 double alpha2_gauss; 2329 Friction* friction=NULL; 2330 2331 /*parameters: */ 2332 double stokesreconditioning; 2333 int analysis_type; 2334 2335 /*inputs: */ 2336 bool onwater; 2337 bool onbed; 2338 bool shelf; 2339 bool isstokes; 2340 2341 /*inputs: */ 2342 Input* vx_input=NULL; 2343 Input* vy_input=NULL; 2344 Input* vz_input=NULL; 2345 2346 /*retrive parameters: */ 2347 parameters->FindParam(&analysis_type,AnalysisTypeEnum); 2348 2349 /*retrieve inputs :*/ 2350 inputs->GetParameterValue(&onwater,ElementOnWaterEnum); 2351 inputs->GetParameterValue(&onbed,ElementOnBedEnum); 2352 inputs->GetParameterValue(&shelf,ElementOnIceShelfEnum); 2353 inputs->GetParameterValue(&isstokes,IsStokesEnum); 2354 2355 /*If on water or not Stokes, skip stiffness: */ 2356 if(onwater || !isstokes) return; 2357 2358 /*recovre material parameters: */ 2359 rho_water=matpar->GetRhoWater(); 2360 rho_ice=matpar->GetRhoIce(); 2361 gravity=matpar->GetG(); 2362 2363 /*retrieve some parameters: */ 2364 this->parameters->FindParam(&stokesreconditioning,StokesReconditioningEnum); 2365 2366 /* Get node coordinates and dof list: */ 2367 GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids); 2368 GetDofList(&doflist[0],&numberofdofspernode); 2369 2370 /* Get gaussian points and weights. Penta is an extrusion of a Tria, we therefore 2371 get tria gaussian points as well as segment gaussian points. For tria gaussian 2372 points, order of integration is 2, because we need to integrate the product tB*D*B' 2373 which is a polynomial of degree 3 (see GaussTria for more details). For segment gaussian 2374 points, same deal, which yields 3 gaussian points.*/ 2375 2376 area_order=5; 2377 num_vert_gauss=5; 2378 2379 /* Get gaussian points and weights (make this a statically initialized list of points? fstd): */ 2380 GaussPenta( &num_area_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &area_gauss_weights,&vert_gauss_coord, &vert_gauss_weights, area_order, num_vert_gauss); 2381 2382 /*Retrieve all inputs we will be needing: */ 2383 vx_input=inputs->GetInput(VxEnum); 2384 vy_input=inputs->GetInput(VyEnum); 2385 vz_input=inputs->GetInput(VzEnum); 2386 2387 /* Start looping on the number of gaussian points: */ 2388 for (igarea=0; igarea<num_area_gauss; igarea++){ 2389 for (igvert=0; igvert<num_vert_gauss; igvert++){ 2390 /*Pick up the gaussian point: */ 2391 area_gauss_weight=*(area_gauss_weights+igarea); 2392 vert_gauss_weight=*(vert_gauss_weights+igvert); 2393 gauss_weight=area_gauss_weight*vert_gauss_weight; 2394 gauss_coord[0]=*(first_gauss_area_coord+igarea); 2395 gauss_coord[1]=*(second_gauss_area_coord+igarea); 2396 gauss_coord[2]=*(third_gauss_area_coord+igarea); 2397 gauss_coord[3]=*(vert_gauss_coord+igvert); 2398 2399 /*Compute strain rate: */ 2400 this->GetStrainRate3d(&epsilon[0],&xyz_list[0][0],gauss_coord,vx_input,vy_input,vz_input); 2401 2402 /*Get viscosity: */ 2403 matice->GetViscosity3dStokes(&viscosity,&epsilon[0]); 2404 2405 /*Get B and Bprime matrices: */ 2406 GetBStokes(&B[0][0],&xyz_list[0][0],gauss_coord); 2407 GetBprimeStokes(&B_prime[0][0],&xyz_list[0][0], gauss_coord); 2408 2409 /* Get Jacobian determinant: */ 2410 GetJacobianDeterminant(&Jdet, &xyz_list[0][0],&gauss_coord[0]); 2411 2412 /* Build the D matrix: we plug the gaussian weight, the thickness, the viscosity, and the jacobian determinant 2413 * onto this scalar matrix, so that we win some computational time: */ 2414 D_scalar=gauss_weight*Jdet; 2415 for (i=0;i<6;i++){ 2416 D[i][i]=D_scalar*viscosity; 2417 } 2418 for (i=6;i<8;i++){ 2419 D[i][i]=-D_scalar*stokesreconditioning; 2420 } 2421 2422 /* Do the triple product tB*D*Bprime: */ 2423 MatrixMultiply(&B[0][0],8,27,1,&D[0][0],8,8,0,&tBD[0][0],0); 2424 MatrixMultiply(&tBD[0][0],27,8,0,&B_prime[0][0],8,27,0,&Ke_gaussian[0][0],0); 2425 2426 /*Add Ke_gaussian and Ke_gaussian to terms in pKe. Watch out for column orientation from matlab: */ 2427 for(i=0;i<27;i++){ 2428 for(j=0;j<27;j++){ 2429 Ke_temp[i][j]+=Ke_gaussian[i][j]; 2430 } 2431 } 2432 } 2433 } 2434 2435 if((onbed==1) && (shelf==0)){ 2436 2437 /*build friction object, used later on: */ 2438 friction=new Friction("3d",inputs,matpar,analysis_type); 2439 2440 for(i=0;i<numgrids2d;i++){ 2441 for(j=0;j<3;j++){ 2442 xyz_list_tria[i][j]=xyz_list[i][j]; 2443 } 2444 } 2445 2446 xfree((void**)&first_gauss_area_coord); xfree((void**)&second_gauss_area_coord); xfree((void**)&third_gauss_area_coord); xfree((void**)&area_gauss_weights); 2447 GaussTria (&num_area_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &area_gauss_weights, 2); 2448 2449 /* Start looping on the number of gauss 2d (nodes on the bedrock) */ 2450 for (igarea=0; igarea<num_area_gauss; igarea++){ 2451 gauss_weight=*(area_gauss_weights+igarea); 2452 gauss_coord[0]=*(first_gauss_area_coord+igarea); 2453 gauss_coord[1]=*(second_gauss_area_coord+igarea); 2454 gauss_coord[2]=*(third_gauss_area_coord+igarea); 2455 gauss_coord[3]=-1; 2456 2457 gauss_coord_tria[0]=*(first_gauss_area_coord+igarea); 2458 gauss_coord_tria[1]=*(second_gauss_area_coord+igarea); 2459 gauss_coord_tria[2]=*(third_gauss_area_coord+igarea); 2460 2461 /*Get the Jacobian determinant */ 2462 tria->GetJacobianDeterminant3d(&Jdet2d, &xyz_list_tria[0][0], gauss_coord_tria); 2463 2464 /*Get L matrix if viscous basal drag present: */ 2465 GetLStokes(&LStokes[0][0], gauss_coord_tria); 2466 GetLprimeStokes(&LprimeStokes[0][0], &xyz_list[0][0], gauss_coord_tria, gauss_coord); 2467 2468 /*Compute strain rate: */ 2469 this->GetStrainRate3d(&epsilon[0],&xyz_list[0][0],gauss_coord,vx_input,vy_input,vz_input); 2470 2471 /*Get viscosity at last iteration: */ 2472 matice->GetViscosity3dStokes(&viscosity,&epsilon[0]); 2473 2474 /*Get normal vecyor to the bed */ 2475 SurfaceNormal(&surface_normal[0],xyz_list_tria); 2476 2477 bed_normal[0]=-surface_normal[0]; //Program is for surface, so the normal to the bed is the opposite of the result 2478 bed_normal[1]=-surface_normal[1]; 2479 bed_normal[2]=-surface_normal[2]; 2480 2481 /*Calculate DL on gauss point */ 2482 friction->GetAlpha2(&alpha2_gauss, gauss_coord,VxEnum,VyEnum,VzEnum); 2483 2484 DLStokes[0][0]=alpha2_gauss*gauss_weight*Jdet2d; 2485 DLStokes[1][1]=alpha2_gauss*gauss_weight*Jdet2d; 2486 DLStokes[2][2]=-alpha2_gauss*gauss_weight*Jdet2d*bed_normal[0]*bed_normal[2]; 2487 DLStokes[3][3]=-alpha2_gauss*gauss_weight*Jdet2d*bed_normal[1]*bed_normal[2]; 2488 DLStokes[4][4]=-alpha2_gauss*gauss_weight*Jdet2d*bed_normal[0]*bed_normal[2]; 2489 DLStokes[5][5]=-alpha2_gauss*gauss_weight*Jdet2d*bed_normal[1]*bed_normal[2]; 2490 DLStokes[6][6]=-viscosity*gauss_weight*Jdet2d*bed_normal[0]; 2491 DLStokes[7][7]=-viscosity*gauss_weight*Jdet2d*bed_normal[1]; 2492 DLStokes[8][8]=-viscosity*gauss_weight*Jdet2d*bed_normal[2]; 2493 DLStokes[9][8]=-viscosity*gauss_weight*Jdet2d*bed_normal[0]/2.0; 2494 DLStokes[10][10]=-viscosity*gauss_weight*Jdet2d*bed_normal[1]/2.0; 2495 DLStokes[11][11]=stokesreconditioning*gauss_weight*Jdet2d*bed_normal[0]; 2496 DLStokes[12][12]=stokesreconditioning*gauss_weight*Jdet2d*bed_normal[1]; 2497 DLStokes[13][13]=stokesreconditioning*gauss_weight*Jdet2d*bed_normal[2]; 2498 2499 /* Do the triple product tL*D*L: */ 2500 MatrixMultiply(&LStokes[0][0],14,numdof2d,1,&DLStokes[0][0],14,14,0,&tLDStokes[0][0],0); 2501 MatrixMultiply(&tLDStokes[0][0],numdof2d,14,0,&LprimeStokes[0][0],14,numdof2d,0,&Ke_drag_gaussian[0][0],0); 2502 2503 for(i=0;i<numdof2d;i++){ 2504 for(j=0;j<numdof2d;j++){ 2505 Ke_temp[i][j]+=Ke_drag_gaussian[i][j]; 2506 } 2507 } 2508 } 2509 2510 /*Free ressources:*/ 2511 delete friction; 2512 2513 } //if ( (onbed==1) && (shelf==0)) 2514 2515 /*Reduce the matrix */ 2516 ReduceMatrixStokes(&Ke_reduced[0][0], &Ke_temp[0][0]); 2517 2518 for(i=0;i<numdof;i++){ 2519 for(j=0;j<numdof;j++){ 2520 K_terms[i][j]+=Ke_reduced[i][j]; 2521 } 2522 } 2523 2524 /*Add Ke_gg to global matrix Kgg: */ 2525 MatSetValues(Kgg,numdof,doflist,numdof,doflist,(const double*)K_terms,ADD_VALUES); 2526 2527 2528 /*Free ressources:*/ 2529 xfree((void**)&first_gauss_area_coord); 2530 xfree((void**)&second_gauss_area_coord); 2531 xfree((void**)&third_gauss_area_coord); 2532 xfree((void**)&area_gauss_weights); 2533 xfree((void**)&vert_gauss_coord); 2534 xfree((void**)&vert_gauss_weights); 2535 2536 return; 2537 } 2538 /*}}}*/ 2539 /*FUNCTION Penta::CreateKMatrixDiagnosticVert {{{1*/ 2540 void Penta::CreateKMatrixDiagnosticVert( Mat Kgg){ 2541 2542 /* local declarations */ 2543 int i,j; 2544 2545 /* node data: */ 2546 const int numgrids=6; 2547 const int NDOF1=1; 2548 const int numdof=NDOF1*numgrids; 2549 double xyz_list[numgrids][3]; 2550 int doflist[numdof]; 2551 int numberofdofspernode; 2552 2553 /* 3d gaussian points: */ 2554 int num_gauss,ig; 2555 double* first_gauss_area_coord = NULL; 2556 double* second_gauss_area_coord = NULL; 2557 double* third_gauss_area_coord = NULL; 2558 double* fourth_gauss_vert_coord = NULL; 2559 double* area_gauss_weights = NULL; 2560 double* vert_gauss_weights = NULL; 2561 int ig1,ig2; 2562 double gauss_weight1,gauss_weight2; 2563 double gauss_coord[4]; 2564 int order_area_gauss; 2565 int num_vert_gauss; 2566 int num_area_gauss; 2567 double gauss_weight; 2568 2569 /* matrices: */ 2570 double Ke_gg[numdof][numdof]={0.0}; 2571 double Ke_gg_gaussian[numdof][numdof]; 2572 double Jdet; 2573 double B[NDOF1][numgrids]; 2574 double Bprime[NDOF1][numgrids]; 2575 double DL_scalar; 2576 2577 /*Collapsed formulation: */ 2578 Tria* tria=NULL; 2579 2580 /*inputs: */ 2581 bool onwater; 2582 bool onsurface; 2583 2584 /*retrieve inputs :*/ 2585 inputs->GetParameterValue(&onwater,ElementOnWaterEnum); 2586 inputs->GetParameterValue(&onsurface,ElementOnSurfaceEnum); 2587 2588 /*If on water, skip stiffness: */ 2589 if(onwater)return; 2590 2591 /*If this element is on the surface, we have a dynamic boundary condition that applies, as a stiffness 2592 * matrix: */ 2593 if(onsurface){ 2594 tria=(Tria*)SpawnTria(3,4,5); //nodes 3,4 and 5 are on the surface 2595 tria->CreateKMatrixDiagnosticSurfaceVert(Kgg); 2596 delete tria; 2597 } 2598 2599 /*Now, onto the formulation for the vertical velocity: */ 2600 2601 /* Get node coordinates and dof list: */ 2602 GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids); 2603 GetDofList(&doflist[0],&numberofdofspernode); 2604 2605 /*Get gaussian points and weights. Penta is an extrusion of a Tria, we therefore 2606 get tria gaussian points as well as segment gaussian points. For tria gaussian 2607 points, order of integration is 2, because we need to integrate the product tB*D*B' 2608 which is a polynomial of degree 3 (see GaussTria for more details). For segment gaussian 2609 points, same deal, which yields 3 gaussian points.*/ 2610 2611 order_area_gauss=2; 2612 num_vert_gauss=2; 2613 2614 GaussPenta( &num_area_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &area_gauss_weights, &fourth_gauss_vert_coord,&vert_gauss_weights,order_area_gauss,num_vert_gauss); 2615 2616 /* Start looping on the number of gaussian points: */ 2617 for (ig1=0; ig1<num_area_gauss; ig1++){ 2618 for (ig2=0; ig2<num_vert_gauss; ig2++){ 2619 2620 /*Pick up the gaussian point: */ 2621 gauss_weight1=*(area_gauss_weights+ig1); 2622 gauss_weight2=*(vert_gauss_weights+ig2); 2623 gauss_weight=gauss_weight1*gauss_weight2; 2624 2625 gauss_coord[0]=*(first_gauss_area_coord+ig1); 2626 gauss_coord[1]=*(second_gauss_area_coord+ig1); 2627 gauss_coord[2]=*(third_gauss_area_coord+ig1); 2628 gauss_coord[3]=*(fourth_gauss_vert_coord+ig2); 2629 2630 /*Get B and Bprime matrices: */ 2631 GetBVert(&B[0][0], &xyz_list[0][0], gauss_coord); 2632 GetBprimeVert(&Bprime[0][0], &xyz_list[0][0], gauss_coord); 2633 2634 /* Get Jacobian determinant: */ 2635 GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss_coord); 2636 DL_scalar=gauss_weight*Jdet; 2637 2638 /* Do the triple product tB*D*Bprime: */ 2639 TripleMultiply( &B[0][0],1,numgrids,1, 2640 &DL_scalar,1,1,0, 2641 &Bprime[0][0],1,numgrids,0, 2642 &Ke_gg_gaussian[0][0],0); 2643 2644 /* Add the Ke_gg_gaussian, and optionally Ke_gg_drag_gaussian onto Ke_gg: */ 2645 for( i=0; i<numdof; i++){ 2646 for(j=0;j<numdof;j++){ 2647 Ke_gg[i][j]+=Ke_gg_gaussian[i][j]; 2648 } 2649 } 2650 } //for (ig2=0; ig2<num_vert_gauss; ig2++) 2651 } //for (ig1=0; ig1<num_area_gauss; ig1++) 2652 2653 /*Add Ke_gg to global matrix Kgg: */ 2654 MatSetValues(Kgg,numdof,doflist,numdof,doflist,(const double*)Ke_gg,ADD_VALUES); 2655 2656 xfree((void**)&first_gauss_area_coord); 2657 xfree((void**)&second_gauss_area_coord); 2658 xfree((void**)&third_gauss_area_coord); 2659 xfree((void**)&fourth_gauss_vert_coord); 2660 xfree((void**)&area_gauss_weights); 2661 xfree((void**)&vert_gauss_weights); 2662 } 2663 /*}}}*/ 2664 /*FUNCTION Penta::CreateKMatrixMelting {{{1*/ 2665 void Penta::CreateKMatrixMelting(Mat Kgg){ 2666 2667 Tria* tria=NULL; 2668 2669 /*inputs: */ 2670 bool onwater; 2671 bool onbed; 2672 2673 /*retrieve inputs :*/ 2674 inputs->GetParameterValue(&onwater,ElementOnWaterEnum); 2675 inputs->GetParameterValue(&onbed,ElementOnBedEnum); 2676 2677 /*If on water, skip: */ 2678 if(onwater)return; 2679 2680 if (!onbed){ 2681 return; 2682 } 2683 else{ 2684 2685 tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria. 2686 tria->CreateKMatrixMelting(Kgg); 2687 delete tria; 2688 return; 2689 } 2690 } 2691 /*}}}*/ 2692 /*FUNCTION Penta::CreateKMatrixPrognostic {{{1*/ 2693 2694 void Penta::CreateKMatrixPrognostic(Mat Kgg){ 2695 2696 /*Collapsed formulation: */ 2697 Tria* tria=NULL; 2698 2699 /*inputs: */ 2700 bool onwater; 2701 bool onbed; 2702 2703 /*retrieve inputs :*/ 2704 inputs->GetParameterValue(&onwater,ElementOnWaterEnum); 2705 inputs->GetParameterValue(&onbed,ElementOnBedEnum); 2706 2707 /*If on water, skip: */ 2708 if(onwater)return; 2709 2710 /*Is this element on the bed? :*/ 2711 if(!onbed)return; 2712 2713 /*Spawn Tria element from the base of the Penta: */ 2714 tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria. 2715 tria->CreateKMatrix(Kgg); 2716 delete tria; 2717 return; 2718 2719 } 2720 /*}}}*/ 2721 /*FUNCTION Penta::CreateKMatrixSlope {{{1*/ 2722 2723 void Penta::CreateKMatrixSlope(Mat Kgg){ 2724 2725 /*Collapsed formulation: */ 2726 Tria* tria=NULL; 2727 2728 /*inputs: */ 2729 bool onwater; 2730 bool onbed; 2731 2732 /*retrieve inputs :*/ 2733 inputs->GetParameterValue(&onwater,ElementOnWaterEnum); 2734 inputs->GetParameterValue(&onbed,ElementOnBedEnum); 2735 2736 2737 /*If on water, skip: */ 2738 if(onwater)return; 2739 2740 /*Is this element on the bed? :*/ 2741 if(!onbed)return; 2742 2743 /*Spawn Tria element from the base of the Penta: */ 2744 tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria. 2745 tria->CreateKMatrix(Kgg); 2746 delete tria; 2747 return; 2748 2749 } 2750 /*}}}*/ 2751 /*FUNCTION Penta::CreateKMatrixThermal {{{1*/ 2752 void Penta::CreateKMatrixThermal(Mat Kgg){ 2753 2754 /* local declarations */ 2755 int i,j; 2756 int found=0; 2757 2758 /* node data: */ 2759 const int numgrids=6; 2760 const int NDOF1=1; 2761 const int numdof=NDOF1*numgrids; 2762 double xyz_list[numgrids][3]; 2763 int doflist[numdof]; 2764 int numberofdofspernode; 2765 2766 /* gaussian points: */ 2767 int num_area_gauss,igarea,igvert; 2768 double* first_gauss_area_coord = NULL; 2769 double* second_gauss_area_coord = NULL; 2770 double* third_gauss_area_coord = NULL; 2771 double* vert_gauss_coord = NULL; 2772 double* area_gauss_weights = NULL; 2773 double* vert_gauss_weights = NULL; 2774 double gauss_weight,area_gauss_weight,vert_gauss_weight; 2775 double gauss_coord[4]; 2776 double gauss_l1l2l3[3]; 2777 2778 int area_order=5; 2779 int num_vert_gauss=5; 2780 2781 int dofs[3]={0,1,2}; 2782 double K[2][2]={0.0}; 2783 2784 double u,v,w; 2785 2786 /*matrices: */ 2787 double K_terms[numdof][numdof]={0.0}; 2788 double Ke_gaussian_conduct[numdof][numdof]; 2789 double Ke_gaussian_advec[numdof][numdof]; 2790 double Ke_gaussian_artdiff[numdof][numdof]; 2791 double Ke_gaussian_transient[numdof][numdof]; 2792 double B[3][numdof]; 2793 double Bprime[3][numdof]; 2794 double B_conduct[3][numdof]; 2795 double B_advec[3][numdof]; 2796 double B_artdiff[2][numdof]; 2797 double Bprime_advec[3][numdof]; 2798 double L[numdof]; 2799 double D_scalar; 2800 double D[3][3]; 2801 double l1l2l3[3]; 2802 double tl1l2l3D[3]; 2803 double tBD[3][numdof]; 2804 double tBD_conduct[3][numdof]; 2805 double tBD_advec[3][numdof]; 2806 double tBD_artdiff[3][numdof]; 2807 double tLD[numdof]; 2808 2809 double Jdet; 2810 2811 /*Material properties: */ 2812 double gravity,rho_ice,rho_water; 2813 double heatcapacity,thermalconductivity; 2814 double mixed_layer_capacity,thermal_exchange_velocity; 2815 2816 /*parameters: */ 2817 double dt,epsvel; 2818 bool artdiff; 2819 2820 /*Collapsed formulation: */ 2821 Tria* tria=NULL; 2822 2823 2824 /*inputs: */ 2825 bool onwater; 2826 bool onbed; 2827 bool shelf; 2828 2829 /*retrieve inputs :*/ 2830 inputs->GetParameterValue(&onwater,ElementOnWaterEnum); 2831 inputs->GetParameterValue(&onbed,ElementOnBedEnum); 2832 inputs->GetParameterValue(&shelf,ElementOnIceShelfEnum); 2833 2834 /*If on water, skip: */ 2835 if(onwater)return; 2836 2837 /* Get node coordinates and dof list: */ 2838 GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids); 2839 GetDofList(&doflist[0],&numberofdofspernode); 2840 2841 // /*recovre material parameters: */ 2842 rho_water=matpar->GetRhoWater(); 2843 rho_ice=matpar->GetRhoIce(); 2844 gravity=matpar->GetG(); 2845 heatcapacity=matpar->GetHeatCapacity(); 2846 thermalconductivity=matpar->GetThermalConductivity(); 2847 2848 /*retrieve some parameters: */ 2849 this->parameters->FindParam(&dt,DtEnum); 2850 this->parameters->FindParam(&artdiff,ArtDiffEnum); 2851 this->parameters->FindParam(&epsvel,EpsVelEnum); 2852 2853 /* Get gaussian points and weights. Penta is an extrusion of a Tria, we therefore 2854 get tria gaussian points as well as segment gaussian points. For tria gaussian 2855 points, order of integration is 2, because we need to integrate the product tB*D*B' 2856 which is a polynomial of degree 3 (see GaussTria for more details). For segment gaussian 2857 points, same deal, which yields 3 gaussian points.: */ 2858 2859 /*Get gaussian points: */ 2860 area_order=2; 2861 num_vert_gauss=2; 2862 2863 GaussPenta( &num_area_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &area_gauss_weights,&vert_gauss_coord, &vert_gauss_weights, area_order, num_vert_gauss); 2864 2865 /* Start looping on the number of gaussian points: */ 2866 for (igarea=0; igarea<num_area_gauss; igarea++){ 2867 for (igvert=0; igvert<num_vert_gauss; igvert++){ 2868 /*Pick up the gaussian point: */ 2869 area_gauss_weight=*(area_gauss_weights+igarea); 2870 vert_gauss_weight=*(vert_gauss_weights+igvert); 2871 gauss_weight=area_gauss_weight*vert_gauss_weight; 2872 gauss_coord[0]=*(first_gauss_area_coord+igarea); 2873 gauss_coord[1]=*(second_gauss_area_coord+igarea); 2874 gauss_coord[2]=*(third_gauss_area_coord+igarea); 2875 gauss_coord[3]=*(vert_gauss_coord+igvert); 2876 2877 /* Get Jacobian determinant: */ 2878 GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss_coord); 2879 2880 /*Conduction: */ 2881 2882 /*Get B_conduct matrix: */ 2883 GetBConduct(&B_conduct[0][0],&xyz_list[0][0],gauss_coord); 2884 2885 /*Build D: */ 2886 D_scalar=gauss_weight*Jdet*(thermalconductivity/(rho_ice*heatcapacity)); 2887 2888 if(dt){ 2889 D_scalar=D_scalar*dt; 2890 } 2891 2892 D[0][0]=D_scalar; D[0][1]=0; D[0][2]=0; 2893 D[1][0]=0; D[1][1]=D_scalar; D[1][2]=0; 2894 D[2][0]=0; D[2][1]=0; D[2][2]=D_scalar; 2895 2896 /* Do the triple product B'*D*B: */ 2897 MatrixMultiply(&B_conduct[0][0],3,numdof,1,&D[0][0],3,3,0,&tBD_conduct[0][0],0); 2898 MatrixMultiply(&tBD_conduct[0][0],numdof,3,0,&B_conduct[0][0],3,numdof,0,&Ke_gaussian_conduct[0][0],0); 2899 2900 /*Advection: */ 2901 2902 /*Get B_advec and Bprime_advec matrices: */ 2903 GetBAdvec(&B_advec[0][0],&xyz_list[0][0],gauss_coord); 2904 GetBprimeAdvec(&Bprime_advec[0][0],&xyz_list[0][0],gauss_coord); 2905 2906 //Build the D matrix 2907 inputs->GetParameterValue(&u, gauss_coord,VxEnum); 2908 inputs->GetParameterValue(&v, gauss_coord,VyEnum); 2909 inputs->GetParameterValue(&w, gauss_coord,VzEnum); 2910 2911 D_scalar=gauss_weight*Jdet; 2912 2913 if(dt){ 2914 D_scalar=D_scalar*dt; 2915 } 2916 2917 D[0][0]=D_scalar*u;D[0][1]=0; D[0][2]=0; 2918 D[1][0]=0; D[1][1]=D_scalar*v;D[1][2]=0; 2919 D[2][0]=0; D[2][1]=0; D[2][2]=D_scalar*w; 2920 2921 /* Do the triple product B'*D*Bprime: */ 2922 MatrixMultiply(&B_advec[0][0],3,numdof,1,&D[0][0],3,3,0,&tBD_advec[0][0],0); 2923 MatrixMultiply(&tBD_advec[0][0],numdof,3,0,&Bprime_advec[0][0],3,numdof,0,&Ke_gaussian_advec[0][0],0); 2924 2925 /*Transient: */ 2926 if(dt){ 2927 GetNodalFunctionsP1(&L[0], gauss_coord); 2928 D_scalar=gauss_weight*Jdet; 2929 D_scalar=D_scalar; 2930 2931 /* Do the triple product L'*D*L: */ 2932 MatrixMultiply(&L[0],numdof,1,0,&D_scalar,1,1,0,&tLD[0],0); 2933 MatrixMultiply(&tLD[0],numdof,1,0,&L[0],1,numdof,0,&Ke_gaussian_transient[0][0],0); 2934 } 2935 else{ 2936 for(i=0;i<numdof;i++){ 2937 for(j=0;j<numdof;j++){ 2938 Ke_gaussian_transient[i][j]=0; 2939 } 2940 } 2941 } 2942 2943 /*Artifficial diffusivity*/ 2944 if(artdiff){ 2945 /*Build K: */ 2946 D_scalar=gauss_weight*Jdet/(pow(u,2)+pow(v,2)+epsvel); 2947 if(dt){ 2948 D_scalar=D_scalar*dt; 2949 } 2950 K[0][0]=D_scalar*pow(u,2); K[0][1]=D_scalar*fabs(u)*fabs(v); 2951 K[1][0]=D_scalar*fabs(u)*fabs(v);K[1][1]=D_scalar*pow(v,2); 2952 2953 /*Get B_artdiff: */ 2954 GetBArtdiff(&B_artdiff[0][0],&xyz_list[0][0],gauss_coord); 2955 2956 /* Do the triple product B'*K*B: */ 2957 MatrixMultiply(&B_artdiff[0][0],2,numdof,1,&K[0][0],2,2,0,&tBD_artdiff[0][0],0); 2958 MatrixMultiply(&tBD_artdiff[0][0],numdof,2,0,&B_artdiff[0][0],2,numdof,0,&Ke_gaussian_artdiff[0][0],0); 2959 } 2960 else{ 2961 for(i=0;i<numdof;i++){ 2962 for(j=0;j<numdof;j++){ 2963 Ke_gaussian_artdiff[i][j]=0; 2964 } 2965 } 2966 } 2967 2968 /*Add Ke_gaussian to pKe: */ 2969 for(i=0;i<numdof;i++){ 2970 for(j=0;j<numdof;j++){ 2971 K_terms[i][j]+=Ke_gaussian_conduct[i][j]+Ke_gaussian_advec[i][j]+Ke_gaussian_transient[i][j]+Ke_gaussian_artdiff[i][j]; 2972 } 2973 } 2974 } 2975 } 2976 2977 /*Add Ke_gg to global matrix Kgg: */ 2978 MatSetValues(Kgg,numdof,doflist,numdof,doflist,(const double*)K_terms,ADD_VALUES); 2979 2980 xfree((void**)&first_gauss_area_coord); 2981 xfree((void**)&second_gauss_area_coord); 2982 xfree((void**)&third_gauss_area_coord); 2983 xfree((void**)&area_gauss_weights); 2984 xfree((void**)&vert_gauss_weights); 2985 xfree((void**)&vert_gauss_coord); 2986 2987 //Ice/ocean heat exchange flux on ice shelf base 2988 if(onbed && shelf){ 2989 2990 tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria. 2991 tria->CreateKMatrixThermal(Kgg); 2992 delete tria; 2993 } 2994 } 2995 /*}}}*/ 2996 /*FUNCTION Penta::CreatePVectorBalancedthickness {{{1*/ 2997 void Penta::CreatePVectorBalancedthickness( Vec pg){ 2998 2999 /*Collapsed formulation: */ 3000 Tria* tria=NULL; 3001 3002 /*flags: */ 3003 bool onbed; 3004 bool onwater; 3005 3006 /*recover some inputs: */ 3007 inputs->GetParameterValue(&onbed,ElementOnBedEnum); 3008 inputs->GetParameterValue(&onwater,ElementOnWaterEnum); 3009 3010 /*If on water, skip: */ 3011 if(onwater)return; 3012 3013 /*Is this element on the bed? :*/ 3014 if(!onbed)return; 3015 3016 /*Spawn Tria element from the base of the Penta: */ 3017 tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria. 3018 tria->CreatePVector(pg); 3019 delete tria; 3020 return; 3021 } 3022 /*}}}*/ 3023 /*FUNCTION Penta::CreatePVectorBalancedvelocities {{{1*/ 3024 void Penta::CreatePVectorBalancedvelocities( Vec pg){ 3025 3026 /*Collapsed formulation: */ 3027 Tria* tria=NULL; 3028 3029 /*flags: */ 3030 bool onbed; 3031 bool onwater; 3032 3033 /*recover some inputs: */ 3034 inputs->GetParameterValue(&onbed,ElementOnBedEnum); 3035 inputs->GetParameterValue(&onwater,ElementOnWaterEnum); 3036 3037 /*If on water, skip: */ 3038 if(onwater)return; 3039 3040 /*Is this element on the bed? :*/ 3041 if(!onbed)return; 3042 3043 /*Spawn Tria element from the base of the Penta: */ 3044 tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria. 3045 tria->CreatePVector(pg); 3046 delete tria; 3047 return; 3048 } 3049 /*}}}*/ 3050 /*FUNCTION Penta::CreatePVectorDiagnosticHoriz {{{1*/ 3051 void Penta::CreatePVectorDiagnosticHoriz( Vec pg){ 3052 3053 int i,j; 3054 3055 /* node data: */ 3056 const int numgrids=6; 3057 const int NDOF2=2; 3058 const int numdof=NDOF2*numgrids; 3059 double xyz_list[numgrids][3]; 3060 int doflist[numdof]; 3061 int numberofdofspernode; 3062 3063 /* parameters: */ 3064 double slope[3]; //do not put 2! this goes into GetParameterDerivativeValue, which addresses slope[3] also! 3065 double driving_stress_baseline; 3066 double thickness; 3067 3068 /* gaussian points: */ 3069 int num_gauss,ig; 3070 double* first_gauss_area_coord = NULL; 3071 double* second_gauss_area_coord = NULL; 3072 double* third_gauss_area_coord = NULL; 3073 double* fourth_gauss_vert_coord = NULL; 3074 double* area_gauss_weights = NULL; 3075 double* vert_gauss_weights = NULL; 3076 double gauss_coord[4]; 3077 int order_area_gauss; 3078 int num_vert_gauss; 3079 int num_area_gauss; 3080 int ig1,ig2; 3081 double gauss_weight1,gauss_weight2; 3082 double gauss_weight; 3083 3084 /* Jacobian: */ 3085 double Jdet; 3086 3087 /*nodal functions: */ 3088 double l1l6[6]; 3089 3090 /*element vector at the gaussian points: */ 3091 double pe_g[numdof]={0.0}; 3092 double pe_g_gaussian[numdof]; 3093 3094 /*Spawning: */ 3095 Tria* tria=NULL; 3096 3097 /*inputs: */ 3098 bool onwater; 3099 bool collapse; 3100 bool onbed; 3101 Input* surface_input=NULL; 3102 Input* thickness_input=NULL; 3103 3104 /*retrieve inputs :*/ 3105 inputs->GetParameterValue(&onwater,ElementOnWaterEnum); 3106 inputs->GetParameterValue(&collapse,CollapseEnum); 3107 inputs->GetParameterValue(&onbed,ElementOnBedEnum); 3108 3109 /*If on water, skip load: */ 3110 if(onwater)return; 3111 3112 /*Figure out if this pentaelem is collapsed. If so, then bailout, except if it is at the 3113 bedrock, in which case we spawn a tria element using the 3 first grids, and use it to build 3114 the load vector. */ 3115 3116 if ((collapse==1) && (onbed==0)){ 3117 /*This element should be collapsed, but this element is not on the bedrock, therefore all its 3118 * dofs have already been frozen! Do nothing: */ 3119 return; 3120 } 3121 else if ((collapse==1) && (onbed==1)){ 3122 3123 /*This element should be collapsed into a tria element at its base. Create this tria element, 3124 *and use its CreatePVector functionality to return an elementary load vector: */ 3125 tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria. 3126 tria->CreatePVector(pg); 3127 delete tria; 3128 return; 3129 } 3130 else{ 3131 3132 /*Implement standard penta element: */ 3133 3134 /* Get node coordinates and dof list: */ 3135 GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids); 3136 GetDofList(&doflist[0],&numberofdofspernode); 3137 3138 /*Get gaussian points and weights :*/ 3139 order_area_gauss=2; 3140 num_vert_gauss=3; 3141 3142 GaussPenta( &num_area_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &area_gauss_weights, &fourth_gauss_vert_coord,&vert_gauss_weights,order_area_gauss,num_vert_gauss); 3143 3144 /*Retrieve all inputs we will be needing: */ 3145 thickness_input=inputs->GetInput(ThicknessEnum); 3146 surface_input=inputs->GetInput(SurfaceEnum); 3147 3148 /* Start looping on the number of gaussian points: */ 3149 for (ig1=0; ig1<num_area_gauss; ig1++){ 3150 for (ig2=0; ig2<num_vert_gauss; ig2++){ 3151 3152 /*Pick up the gaussian point: */ 3153 gauss_weight1=*(area_gauss_weights+ig1); 3154 gauss_weight2=*(vert_gauss_weights+ig2); 3155 gauss_weight=gauss_weight1*gauss_weight2; 3156 3157 gauss_coord[0]=*(first_gauss_area_coord+ig1); 3158 gauss_coord[1]=*(second_gauss_area_coord+ig1); 3159 gauss_coord[2]=*(third_gauss_area_coord+ig1); 3160 gauss_coord[3]=*(fourth_gauss_vert_coord+ig2); 3161 3162 /*Compute thickness at gaussian point: */ 3163 thickness_input->GetParameterValue(&thickness, gauss_coord); 3164 3165 /*Compute slope at gaussian point: */ 3166 surface_input->GetParameterDerivativeValue(&slope[0],&xyz_list[0][0],gauss_coord); 3167 3168 /* Get Jacobian determinant: */ 3169 GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss_coord); 3170 3171 /*Get nodal functions: */ 3172 GetNodalFunctionsP1(l1l6, gauss_coord); 3173 3174 /*Compute driving stress: */ 3175 driving_stress_baseline=matpar->GetRhoIce()*matpar->GetG(); 3176 3177 /*Build pe_g_gaussian vector: */ 3178 for (i=0;i<numgrids;i++){ 3179 for (j=0;j<NDOF2;j++){ 3180 pe_g_gaussian[i*NDOF2+j]=-driving_stress_baseline*slope[j]*Jdet*gauss_weight*l1l6[i]; 3181 } 3182 } 3183 3184 /*Add pe_g_gaussian vector to pe_g: */ 3185 for( i=0; i<numdof; i++)pe_g[i]+=pe_g_gaussian[i]; 3186 3187 } //for (ig2=0; ig2<num_vert_gauss; ig2++) 3188 } //for (ig1=0; ig1<num_area_gauss; ig1++) 3189 3190 } //else if ((collapse==1) && (onbed==1)) 3191 3192 /*Add pe_g to global vector pg: */ 3193 VecSetValues(pg,numdof,doflist,(const double*)pe_g,ADD_VALUES); 3194 3195 xfree((void**)&first_gauss_area_coord); 3196 xfree((void**)&second_gauss_area_coord); 3197 xfree((void**)&third_gauss_area_coord); 3198 xfree((void**)&fourth_gauss_vert_coord); 3199 xfree((void**)&area_gauss_weights); 3200 xfree((void**)&vert_gauss_weights); 3201 3202 } 3203 /*}}}*/ 3204 /*FUNCTION Penta::CreatePVectorAdjointHoriz{{{1*/ 3205 void Penta::CreatePVectorAdjointHoriz(Vec p_g){ 1972 3206 1973 3207 int i; 1974 int analysis_counter; 3208 Tria* tria=NULL; 3209 3210 /*inputs: */ 3211 bool onwater; 3212 bool collapse; 3213 bool onsurface; 3214 bool onbed; 3215 3216 /*retrieve inputs :*/ 3217 inputs->GetParameterValue(&onwater,ElementOnWaterEnum); 3218 inputs->GetParameterValue(&collapse,CollapseEnum); 3219 inputs->GetParameterValue(&onbed,ElementOnBedEnum); 3220 inputs->GetParameterValue(&onsurface,ElementOnSurfaceEnum); 3221 3222 /*If on water, skip: */ 3223 if(onwater) return; 3224 3225 /*Bail out if this element if: 3226 * -> Non collapsed and not on the surface 3227 * -> collapsed (2d model) and not on bed) */ 3228 if ((!collapse && !onsurface) || (collapse && !onbed)){ 3229 return; 3230 } 3231 else if (collapse){ 3232 3233 /*This element should be collapsed into a tria element at its base. Create this tria element, 3234 * and compute pe_g*/ 3235 tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria (lower face). 3236 tria->CreatePVectorAdjointHoriz(p_g); 3237 delete tria; 3238 return; 3239 } 3240 else{ 3241 3242 tria=(Tria*)SpawnTria(3,4,5); //grids 3, 4 and 5 make the new tria (upper face). 3243 tria->CreatePVectorAdjointHoriz(p_g); 3244 delete tria; 3245 return; 3246 } 3247 } 3248 /*}}}*/ 3249 /*FUNCTION Penta::CreatePVectorDiagnosticHutter{{{1*/ 3250 void Penta::CreatePVectorDiagnosticHutter(Vec pg){ 3251 3252 /*Collapsed formulation: */ 3253 Beam* beam=NULL; 3254 int i; 3255 3256 /*flags: */ 3257 bool onwater; 3258 3259 /*recover some inputs: */ 3260 inputs->GetParameterValue(&onwater,ElementOnWaterEnum); 3261 3262 /*If on water, skip: */ 3263 if(onwater)return; 3264 3265 /*Spawn 3 beam elements: */ 3266 for(i=0;i<3;i++){ 3267 beam=(Beam*)SpawnBeam(i,i+3); //[0 3], [1 4] and [2 5] are the four vertical edges of the Penta 3268 beam->CreatePVector(pg); 3269 } 3270 3271 /*clean up*/ 3272 delete beam; 3273 3274 } 3275 /*}}}*/ 3276 /*FUNCTION Penta::CreatePVectorDiagnosticStokes {{{1*/ 3277 void Penta::CreatePVectorDiagnosticStokes( Vec pg){ 3278 3279 /*indexing: */ 3280 int i,j; 3281 3282 const int numgrids=6; 3283 const int DOFPERGRID=4; 3284 const int numdof=numgrids*DOFPERGRID; 3285 const int numgrids2d=3; 3286 int numdof2d=numgrids2d*DOFPERGRID; 3287 int doflist[numdof]; 3288 int numberofdofspernode; 3289 3290 /*Material properties: */ 3291 double gravity,rho_ice,rho_water; 3292 3293 /*parameters: */ 3294 double xyz_list_tria[numgrids2d][3]; 3295 double xyz_list[numgrids][3]; 3296 double surface_normal[3]; 3297 double bed_normal[3]; 3298 double bed; 3299 3300 /* gaussian points: */ 3301 int num_area_gauss; 3302 int igarea,igvert; 3303 double* first_gauss_area_coord = NULL; 3304 double* second_gauss_area_coord = NULL; 3305 double* third_gauss_area_coord = NULL; 3306 double* vert_gauss_coord = NULL; 3307 double* area_gauss_weights = NULL; 3308 double* vert_gauss_weights = NULL; 3309 3310 /* specific gaussian point: */ 3311 double gauss_weight,area_gauss_weight,vert_gauss_weight; 3312 double gauss_coord[4]; 3313 double gauss_coord_tria[3]; 3314 3315 int area_order=5; 3316 int num_vert_gauss=5; 3317 3318 double epsilon[6]; /* epsilon=[exx,eyy,ezz,exy,exz,eyz];*/ 3319 double viscosity; 3320 double water_pressure; 3321 int dofs[3]={0,1,2}; 3322 3323 /*matrices: */ 3324 double Pe_temp[27]={0.0}; //for the six nodes and the bubble 3325 double Pe_gaussian[27]={0.0}; //for the six nodes and the bubble 3326 double Ke_temp[27][3]={0.0}; //for the six nodes and the bubble 3327 double Pe_reduced[numdof]; //for the six nodes only 3328 double Ke_gaussian[27][3]; 3329 double L[3]; //for the three nodes of the bed 3330 double l1l7[7]; //for the six nodes and the bubble 3331 double B[8][27]; 3332 double B_prime[8][27]; 3333 double B_prime_bubble[8][3]; 3334 double Jdet; 3335 double Jdet2d; 3336 double D[8][8]={0.0}; 3337 double D_scalar; 3338 double tBD[27][8]; 3339 double P_terms[numdof]={0.0}; 3340 3341 Tria* tria=NULL; 3342 3343 /*parameters: */ 3344 double stokesreconditioning; 3345 3346 /*inputs: */ 3347 bool onwater; 3348 bool onbed; 3349 bool shelf; 3350 bool isstokes; 3351 Input* vx_input=NULL; 3352 Input* vy_input=NULL; 3353 Input* vz_input=NULL; 3354 Input* bed_input=NULL; 3355 3356 /*retrieve inputs :*/ 3357 inputs->GetParameterValue(&onwater,ElementOnWaterEnum); 3358 inputs->GetParameterValue(&onbed,ElementOnBedEnum); 3359 inputs->GetParameterValue(&shelf,ElementOnIceShelfEnum); 3360 inputs->GetParameterValue(&isstokes,IsStokesEnum); 3361 3362 /*retrieve some parameters: */ 3363 this->parameters->FindParam(&stokesreconditioning,StokesReconditioningEnum); 3364 3365 /*If on water or not Stokes, skip load: */ 3366 if(onwater || !isstokes) return; 3367 3368 /*If on water, skip load: */ 3369 if(onwater)return; 3370 3371 /*recovre material parameters: */ 3372 rho_water=matpar->GetRhoWater(); 3373 rho_ice=matpar->GetRhoIce(); 3374 gravity=matpar->GetG(); 3375 3376 /* Get node coordinates and dof list: */ 3377 GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids); 3378 GetDofList(&doflist[0],&numberofdofspernode); 3379 3380 /* Get gaussian points and weights. Penta is an extrusion of a Tria, we therefore 3381 get tria gaussian points as well as segment gaussian points. For tria gaussian 3382 points, order of integration is 2, because we need to integrate the product tB*D*B' 3383 which is a polynomial of degree 3 (see GaussTria for more details). For segment gaussian 3384 points, same deal, which yields 3 gaussian points.*/ 3385 3386 /* Get gaussian points and weights (make this a statically initialized list of points? fstd): */ 3387 GaussPenta( &num_area_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &area_gauss_weights,&vert_gauss_coord, &vert_gauss_weights, area_order, num_vert_gauss); 3388 3389 /*Retrieve all inputs we will be needing: */ 3390 vx_input=inputs->GetInput(VxEnum); 3391 vy_input=inputs->GetInput(VyEnum); 3392 vz_input=inputs->GetInput(VzEnum); 3393 bed_input=inputs->GetInput(BedEnum); 3394 3395 /* Start looping on the number of gaussian points: */ 3396 for (igarea=0; igarea<num_area_gauss; igarea++){ 3397 for (igvert=0; igvert<num_vert_gauss; igvert++){ 3398 /*Pick up the gaussian point: */ 3399 area_gauss_weight=*(area_gauss_weights+igarea); 3400 vert_gauss_weight=*(vert_gauss_weights+igvert); 3401 gauss_weight=area_gauss_weight*vert_gauss_weight; 3402 gauss_coord[0]=*(first_gauss_area_coord+igarea); 3403 gauss_coord[1]=*(second_gauss_area_coord+igarea); 3404 gauss_coord[2]=*(third_gauss_area_coord+igarea); 3405 gauss_coord[3]=*(vert_gauss_coord+igvert); 3406 3407 /*Compute strain rate and viscosity: */ 3408 this->GetStrainRate3d(&epsilon[0],&xyz_list[0][0],gauss_coord,vx_input,vy_input,vz_input); 3409 matice->GetViscosity3dStokes(&viscosity,&epsilon[0]); 3410 3411 /* Get Jacobian determinant: */ 3412 GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss_coord); 3413 3414 /* Get nodal functions */ 3415 GetNodalFunctionsMINI(&l1l7[0], gauss_coord); 3416 3417 /* Build gaussian vector */ 3418 for(i=0;i<numgrids+1;i++){ 3419 Pe_gaussian[i*DOFPERGRID+2]=-rho_ice*gravity*Jdet*gauss_weight*l1l7[i]; 3420 } 3421 3422 /*Add Pe_gaussian to terms in Pe_temp. Watch out for column orientation from matlab: */ 3423 for(i=0;i<27;i++){ 3424 Pe_temp[i]+=Pe_gaussian[i]; 3425 } 3426 3427 /*Get B and Bprime matrices: */ 3428 GetBStokes(&B[0][0],&xyz_list[0][0],gauss_coord); 3429 GetBprimeStokes(&B_prime[0][0],&xyz_list[0][0], gauss_coord); 3430 3431 /*Get bubble part of Bprime */ 3432 for(i=0;i<8;i++){ 3433 for(j=0;j<3;j++){ 3434 B_prime_bubble[i][j]=B_prime[i][j+24]; 3435 } 3436 } 3437 3438 /* Build the D matrix: we plug the gaussian weight, the thickness, the viscosity, and the jacobian determinant 3439 * onto this scalar matrix, so that we win some computational time: */ 3440 D_scalar=gauss_weight*Jdet; 3441 for (i=0;i<6;i++){ 3442 D[i][i]=D_scalar*viscosity; 3443 } 3444 for (i=6;i<8;i++){ 3445 D[i][i]=-D_scalar*stokesreconditioning; 3446 } 3447 3448 /* Do the triple product tB*D*Bprime: */ 3449 MatrixMultiply(&B[0][0],8,27,1,&D[0][0],8,8,0,&tBD[0][0],0); 3450 MatrixMultiply(&tBD[0][0],27,8,0,&B_prime_bubble[0][0],8,3,0,&Ke_gaussian[0][0],0); 3451 3452 /*Add Ke_gaussian and Ke_gaussian to terms in pKe. Watch out for column orientation from matlab: */ 3453 for(i=0;i<27;i++){ 3454 for(j=0;j<3;j++){ 3455 Ke_temp[i][j]+=Ke_gaussian[i][j]; 3456 } 3457 } 3458 } 3459 } 3460 3461 /*Deal with 2d friction at the bedrock interface: */ 3462 if ( (onbed==1) && (shelf==1)){ 3463 3464 for(i=0;i<numgrids2d;i++){ 3465 for(j=0;j<3;j++){ 3466 xyz_list_tria[i][j]=xyz_list[i][j]; 3467 } 3468 } 3469 3470 xfree((void**)&first_gauss_area_coord); xfree((void**)&second_gauss_area_coord); xfree((void**)&third_gauss_area_coord); xfree((void**)&area_gauss_weights); 3471 GaussTria (&num_area_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &area_gauss_weights, 2); 3472 3473 /* Start looping on the number of gauss 2d (nodes on the bedrock) */ 3474 for (igarea=0; igarea<num_area_gauss; igarea++){ 3475 gauss_weight=*(area_gauss_weights+igarea); 3476 gauss_coord[0]=*(first_gauss_area_coord+igarea); 3477 gauss_coord[1]=*(second_gauss_area_coord+igarea); 3478 gauss_coord[2]=*(third_gauss_area_coord+igarea); 3479 gauss_coord[3]=-1; 3480 3481 gauss_coord_tria[0]=*(first_gauss_area_coord+igarea); 3482 gauss_coord_tria[1]=*(second_gauss_area_coord+igarea); 3483 gauss_coord_tria[2]=*(third_gauss_area_coord+igarea); 3484 3485 /*Get the Jacobian determinant */ 3486 tria->GetJacobianDeterminant3d(&Jdet2d, &xyz_list_tria[0][0], gauss_coord_tria); 3487 3488 /* Get bed at gaussian point */ 3489 bed_input->GetParameterValue(&bed, gauss_coord); 3490 3491 /*Get L matrix : */ 3492 tria->GetL(&L[0], &xyz_list[0][0], gauss_coord_tria,1); 3493 3494 /*Get water_pressure at gaussian point */ 3495 water_pressure=gravity*rho_water*bed; 3496 3497 /*Get normal vecyor to the bed */ 3498 SurfaceNormal(&surface_normal[0],xyz_list_tria); 3499 3500 bed_normal[0]=-surface_normal[0]; //Program is for surface, so the normal to the bed is the opposite of the result 3501 bed_normal[1]=-surface_normal[1]; 3502 bed_normal[2]=-surface_normal[2]; 3503 3504 for(i=0;i<numgrids2d;i++){ 3505 for(j=0;j<3;j++){ 3506 Pe_temp[i*DOFPERGRID+j]+=water_pressure*gauss_weight*Jdet2d*L[i]*bed_normal[j]; 3507 } 3508 } 3509 } 3510 } //if ( (onbed==1) && (shelf==1)) 3511 3512 /*Reduce the matrix */ 3513 ReduceVectorStokes(&Pe_reduced[0], &Ke_temp[0][0], &Pe_temp[0]); 3514 3515 for(i=0;i<numdof;i++){ 3516 P_terms[i]+=Pe_reduced[i]; 3517 } 3518 3519 /*Add P_terms to global vector pg: */ 3520 VecSetValues(pg,numdof,doflist,(const double*)P_terms,ADD_VALUES); 3521 3522 /*Free ressources:*/ 3523 xfree((void**)&first_gauss_area_coord); 3524 xfree((void**)&second_gauss_area_coord); 3525 xfree((void**)&third_gauss_area_coord); 3526 xfree((void**)&area_gauss_weights); 3527 xfree((void**)&vert_gauss_coord); 3528 xfree((void**)&vert_gauss_weights); 3529 3530 } 3531 /*}}}*/ 3532 /*FUNCTION Penta::CreatePVectorAdjointStokes{{{1*/ 3533 void Penta::CreatePVectorAdjointStokes(Vec p_g){ 3534 3535 int i; 3536 Tria* tria=NULL; 3537 3538 /*inputs: */ 3539 bool onwater; 3540 bool onsurface; 3541 3542 /*retrieve inputs :*/ 3543 inputs->GetParameterValue(&onwater,ElementOnWaterEnum); 3544 inputs->GetParameterValue(&onsurface,ElementOnSurfaceEnum); 3545 3546 /*If on water, skip: */ 3547 if(onwater || !onsurface)return; 3548 3549 /*Call Tria's function*/ 3550 tria=(Tria*)SpawnTria(3,4,5); //grids 3, 4 and 5 make the new tria (upper face). 3551 tria->CreatePVectorAdjointStokes(p_g); 3552 delete tria; 3553 return; 3554 } 3555 /*}}}*/ 3556 /*FUNCTION Penta::CreatePVectorDiagnosticVert {{{1*/ 3557 void Penta::CreatePVectorDiagnosticVert( Vec pg){ 3558 3559 int i; 3560 3561 /* node data: */ 3562 const int numgrids=6; 3563 const int NDOF1=1; 3564 const int numdof=NDOF1*numgrids; 3565 double xyz_list[numgrids][3]; 3566 int doflist[numdof]; 3567 int numberofdofspernode; 3568 3569 /* gaussian points: */ 3570 int num_gauss,ig; 3571 double* first_gauss_area_coord = NULL; 3572 double* second_gauss_area_coord = NULL; 3573 double* third_gauss_area_coord = NULL; 3574 double* fourth_gauss_vert_coord = NULL; 3575 double* area_gauss_weights = NULL; 3576 double* vert_gauss_weights = NULL; 3577 double gauss_coord[4]; 3578 int order_area_gauss; 3579 int num_vert_gauss; 3580 int num_area_gauss; 3581 int ig1,ig2; 3582 double gauss_weight1,gauss_weight2; 3583 double gauss_weight; 3584 3585 /* Jacobian: */ 3586 double Jdet; 3587 3588 /*element vector at the gaussian points: */ 3589 double pe_g[numdof]={0.0}; 3590 double pe_g_gaussian[numdof]; 3591 double l1l6[6]; 3592 3593 /*Spawning: */ 3594 Tria* tria=NULL; 3595 3596 /*input parameters for structural analysis (diagnostic): */ 3597 double du[3]; 3598 double dv[3]; 3599 double dudx,dvdy; 3600 int dofs1[1]={0}; 3601 int dofs2[1]={1}; 3602 3603 /*inputs: */ 3604 bool onwater; 3605 bool onbed; 3606 Input* vx_input=NULL; 3607 Input* vy_input=NULL; 3608 3609 /*retrieve inputs :*/ 3610 inputs->GetParameterValue(&onwater,ElementOnWaterEnum); 3611 inputs->GetParameterValue(&onbed,ElementOnBedEnum); 3612 3613 /*If on water, skip: */ 3614 if(onwater)return; 3615 3616 /*If we are on the bedrock, spawn a tria on the bedrock, and use it to build the 3617 *diagnostic base vertical stifness: */ 3618 if(onbed){ 3619 tria=(Tria*)SpawnTria(0,1,2); //nodes 0, 1 and 2 are on the bedrock 3620 tria->CreatePVectorDiagnosticBaseVert(pg); 3621 delete tria; 3622 } 3623 3624 /*Now, handle the standard penta element: */ 3625 /* Get node coordinates and dof list: */ 3626 GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids); 3627 GetDofList(&doflist[0],&numberofdofspernode); 3628 3629 /*Get gaussian points and weights :*/ 3630 order_area_gauss=2; 3631 num_vert_gauss=2; 3632 3633 GaussPenta( &num_area_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &area_gauss_weights, &fourth_gauss_vert_coord,&vert_gauss_weights,order_area_gauss,num_vert_gauss); 3634 3635 /*Retrieve all inputs we will be needing: */ 3636 vx_input=inputs->GetInput(VxEnum); 3637 vy_input=inputs->GetInput(VyEnum); 3638 3639 /* Start looping on the number of gaussian points: */ 3640 for (ig1=0; ig1<num_area_gauss; ig1++){ 3641 for (ig2=0; ig2<num_vert_gauss; ig2++){ 3642 3643 /*Pick up the gaussian point: */ 3644 gauss_weight1=*(area_gauss_weights+ig1); 3645 gauss_weight2=*(vert_gauss_weights+ig2); 3646 gauss_weight=gauss_weight1*gauss_weight2; 3647 3648 gauss_coord[0]=*(first_gauss_area_coord+ig1); 3649 gauss_coord[1]=*(second_gauss_area_coord+ig1); 3650 gauss_coord[2]=*(third_gauss_area_coord+ig1); 3651 gauss_coord[3]=*(fourth_gauss_vert_coord+ig2); 3652 3653 /*Get velocity derivative, with respect to x and y: */ 3654 3655 vx_input->GetParameterDerivativeValue(&du[0],&xyz_list[0][0],gauss_coord); 3656 vy_input->GetParameterDerivativeValue(&dv[0],&xyz_list[0][0],gauss_coord); 3657 dudx=du[0]; 3658 dvdy=dv[1]; 3659 3660 /* Get Jacobian determinant: */ 3661 GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss_coord); 3662 3663 /*Get nodal functions: */ 3664 GetNodalFunctionsP1(l1l6, gauss_coord); 3665 3666 /*Build pe_g_gaussian vector: */ 3667 for (i=0;i<numgrids;i++){ 3668 pe_g_gaussian[i]=(dudx+dvdy)*Jdet*gauss_weight*l1l6[i]; 3669 } 3670 3671 /*Add pe_g_gaussian vector to pe_g: */ 3672 for( i=0; i<numdof; i++)pe_g[i]+=pe_g_gaussian[i]; 3673 3674 } //for (ig2=0; ig2<num_vert_gauss; ig2++) 3675 } //for (ig1=0; ig1<num_area_gauss; ig1++) 3676 3677 /*Add pe_g to global vector pg: */ 3678 VecSetValues(pg,numdof,doflist,(const double*)pe_g,ADD_VALUES); 3679 3680 xfree((void**)&first_gauss_area_coord); 3681 xfree((void**)&second_gauss_area_coord); 3682 xfree((void**)&third_gauss_area_coord); 3683 xfree((void**)&fourth_gauss_vert_coord); 3684 xfree((void**)&area_gauss_weights); 3685 xfree((void**)&vert_gauss_weights); 3686 } 3687 /*}}}*/ 3688 /*FUNCTION Penta::CreatePVectorMelting {{{1*/ 3689 void Penta::CreatePVectorMelting( Vec pg){ 3690 return; 3691 } 3692 /*}}}*/ 3693 /*FUNCTION Penta::CreatePVectorPrognostic {{{1*/ 3694 3695 void Penta::CreatePVectorPrognostic( Vec pg){ 3696 3697 /*Collapsed formulation: */ 3698 Tria* tria=NULL; 3699 3700 /*inputs: */ 3701 bool onwater; 3702 bool onbed; 3703 3704 /*retrieve inputs :*/ 3705 inputs->GetParameterValue(&onwater,ElementOnWaterEnum); 3706 inputs->GetParameterValue(&onbed,ElementOnBedEnum); 1975 3707 1976 /*go into parameters and get the analysis_counter: */ 1977 this->parameters->FindParam(&analysis_counter,AnalysisCounterEnum); 1978 1979 /*out of grids g0,g1 and g2 from Penta, build a tria element: */ 1980 Tria* tria=NULL; 1981 int indices[3]; 1982 int zero=0; 1983 Parameters* tria_parameters=NULL; 1984 Inputs* tria_inputs=NULL; 1985 Results* tria_results=NULL; 1986 1987 indices[0]=g0; 1988 indices[1]=g1; 1989 indices[2]=g2; 1990 1991 tria_parameters=this->parameters; 1992 tria_inputs=(Inputs*)this->inputs->SpawnTriaInputs(indices); 1993 tria_results=(Results*)this->results->SpawnTriaResults(indices); 1994 1995 tria=new Tria(); 1996 tria->id=this->id; 1997 tria->inputs=tria_inputs; 1998 tria->results=tria_results; 1999 tria->parameters=tria_parameters; 2000 tria->element_type=P1Enum; //Only P1 CG for now 2001 this->SpawnTriaHook(dynamic_cast<TriaHook*>(tria),&indices[0]); 2002 2003 /*recover nodes, matice and matpar: */ 2004 tria->nodes=(Node**)tria->hnodes[analysis_counter]->deliverp(); 2005 tria->matice=(Matice*)tria->hmatice->delivers(); 2006 tria->matpar=(Matpar*)tria->hmatpar->delivers(); 2007 2008 return tria; 2009 } 2010 /*}}}*/ 2011 /*FUNCTION Penta::SpawnBeam {{{1*/ 2012 void* Penta::SpawnBeam(int g0, int g1){ 2013 2014 int i; 2015 2016 /*out of grids g0,g1 and g2 from Penta, build a beam element: */ 2017 Beam* beam=NULL; 2018 int indices[2]; 2019 int zero=0; 2020 Parameters *beam_parameters = NULL; 2021 Inputs *beam_inputs = NULL; 2022 2023 indices[0]=g0; 2024 indices[1]=g1; 2025 2026 beam_parameters=this->parameters; 2027 beam_inputs=(Inputs*)this->inputs->SpawnBeamInputs(indices); 2028 2029 beam=new Beam(); 2030 beam->id=this->id; 2031 beam->inputs=beam_inputs; 2032 beam->parameters=beam_parameters; 2033 2034 /*now deal with ndoes,matice and matpar: */ 2035 beam->nodes=(Node**)xmalloc(2*sizeof(Node*)); 2036 for(i=0;i<2;i++)beam->nodes[i]=this->nodes[indices[i]]; 2037 beam->matice=this->matice; 2038 beam->matpar=this->matpar; 2039 2040 return beam; 2041 } 2042 /*}}}*/ 2043 /*FUNCTION Penta::SpawnSing {{{1*/ 2044 void* Penta::SpawnSing(int index){ 2045 2046 Sing* sing=NULL; 2047 int zero=0; 2048 Parameters *sing_parameters = NULL; 2049 Inputs *sing_inputs = NULL; 2050 2051 sing_parameters=this->parameters; 2052 sing_inputs=(Inputs*)this->inputs->SpawnSingInputs(index); 2053 2054 sing=new Sing(); 2055 sing->id=this->id; 2056 sing->inputs=sing_inputs; 2057 sing->parameters=sing_parameters; 2058 2059 /*now deal with nodes,matice and matpar: */ 2060 sing->node=this->nodes[index]; 2061 sing->matice=this->matice; 2062 sing->matpar=this->matpar; 2063 2064 return sing; 3708 /*If on water, skip: */ 3709 if(onwater)return; 3710 3711 /*Is this element on the bed? :*/ 3712 if(!onbed)return; 3713 3714 /*Spawn Tria element from the base of the Penta: */ 3715 tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria. 3716 tria->CreatePVector(pg); 3717 delete tria; 3718 return; 3719 } 3720 /*}}}*/ 3721 /*FUNCTION Penta::CreatePVectorSlope {{{1*/ 3722 3723 void Penta::CreatePVectorSlope( Vec pg){ 3724 3725 /*Collapsed formulation: */ 3726 Tria* tria=NULL; 3727 3728 /*inputs: */ 3729 bool onwater; 3730 bool onbed; 3731 3732 /*retrieve inputs :*/ 3733 inputs->GetParameterValue(&onwater,ElementOnWaterEnum); 3734 inputs->GetParameterValue(&onbed,ElementOnBedEnum); 3735 3736 /*If on water, skip: */ 3737 if(onwater)return; 3738 3739 /*Is this element on the bed? :*/ 3740 if(!onbed)return; 3741 3742 /*Spawn Tria element from the base of the Penta: */ 3743 tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria. 3744 tria->CreatePVector(pg); 3745 delete tria; 3746 return; 3747 } 3748 /*}}}*/ 3749 /*FUNCTION Penta::CreatePVectorThermal {{{1*/ 3750 void Penta::CreatePVectorThermal( Vec pg){ 3751 3752 /*indexing: */ 3753 int i,j; 3754 int found=0; 3755 3756 const int numgrids=6; 3757 const int NDOF1=1; 3758 const int numdof=numgrids*NDOF1; 3759 int doflist[numdof]; 3760 int numberofdofspernode; 3761 3762 /*Grid data: */ 3763 double xyz_list[numgrids][3]; 3764 3765 /* gaussian points: */ 3766 int num_area_gauss,igarea,igvert; 3767 double* first_gauss_area_coord = NULL; 3768 double* second_gauss_area_coord = NULL; 3769 double* third_gauss_area_coord = NULL; 3770 double* vert_gauss_coord = NULL; 3771 double* area_gauss_weights = NULL; 3772 double* vert_gauss_weights = NULL; 3773 double gauss_weight,area_gauss_weight,vert_gauss_weight; 3774 double gauss_coord[4]; 3775 int area_order=2; 3776 int num_vert_gauss=3; 3777 3778 double temperature_list[numgrids]; 3779 double temperature; 3780 3781 /*Material properties: */ 3782 double gravity,rho_ice,rho_water; 3783 double mixed_layer_capacity,heatcapacity; 3784 double beta,meltingpoint,thermal_exchange_velocity; 3785 3786 /* element parameters: */ 3787 int friction_type; 3788 3789 int dofs[3]={0,1,2}; 3790 int dofs1[1]={0}; 3791 3792 /*matrices: */ 3793 double P_terms[numdof]={0.0}; 3794 double L[numdof]; 3795 double l1l2l3[3]; 3796 double alpha2_list[3]; 3797 double basalfriction_list[3]={0.0}; 3798 double basalfriction; 3799 double epsilon[6]; 3800 double epsilon_sqr[3][3]; 3801 double epsilon_matrix[3][3]; 3802 3803 double Jdet; 3804 double viscosity; 3805 double epsilon_eff; 3806 double phi; 3807 double t_pmp; 3808 double scalar; 3809 double scalar_def; 3810 double scalar_ocean; 3811 double scalar_transient; 3812 3813 /*Collapsed formulation: */ 3814 Tria* tria=NULL; 3815 3816 /*parameters: */ 3817 double dt; 3818 3819 /*inputs: */ 3820 bool onwater; 3821 bool onbed; 3822 bool shelf; 3823 Input* vx_input=NULL; 3824 Input* vy_input=NULL; 3825 Input* vz_input=NULL; 3826 3827 /*retrieve inputs :*/ 3828 inputs->GetParameterValue(&onwater,ElementOnWaterEnum); 3829 inputs->GetParameterValue(&onbed,ElementOnBedEnum); 3830 inputs->GetParameterValue(&shelf,ElementOnIceShelfEnum); 3831 3832 /*retrieve some parameters: */ 3833 this->parameters->FindParam(&dt,DtEnum); 3834 3835 /*If on water, skip: */ 3836 if(onwater)return; 3837 3838 /* Get node coordinates and dof list: */ 3839 GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids); 3840 GetDofList(&doflist[0],&numberofdofspernode); 3841 3842 /*recovre material parameters: */ 3843 rho_water=matpar->GetRhoWater(); 3844 rho_ice=matpar->GetRhoIce(); 3845 gravity=matpar->GetG(); 3846 heatcapacity=matpar->GetHeatCapacity(); 3847 beta=matpar->GetBeta(); 3848 meltingpoint=matpar->GetMeltingPoint(); 3849 3850 /* Get gaussian points and weights. Penta is an extrusion of a Tria, we therefore 3851 get tria gaussian points as well as segment gaussian points. For tria gaussian 3852 points, order of integration is 2, because we need to integrate the product tB*D*B' 3853 which is a polynomial of degree 3 (see GaussTria for more details). For segment gaussian 3854 points, same deal, which yields 3 gaussian points.: */ 3855 3856 /*Get gaussian points: */ 3857 GaussPenta( &num_area_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &area_gauss_weights,&vert_gauss_coord, &vert_gauss_weights, area_order, num_vert_gauss); 3858 3859 /*Retrieve all inputs we will be needing: */ 3860 vx_input=inputs->GetInput(VxEnum); 3861 vy_input=inputs->GetInput(VyEnum); 3862 vz_input=inputs->GetInput(VzEnum); 3863 3864 /* Start looping on the number of gaussian points: */ 3865 for (igarea=0; igarea<num_area_gauss; igarea++){ 3866 for (igvert=0; igvert<num_vert_gauss; igvert++){ 3867 /*Pick up the gaussian point: */ 3868 area_gauss_weight=*(area_gauss_weights+igarea); 3869 vert_gauss_weight=*(vert_gauss_weights+igvert); 3870 gauss_weight=area_gauss_weight*vert_gauss_weight; 3871 gauss_coord[0]=*(first_gauss_area_coord+igarea); 3872 gauss_coord[1]=*(second_gauss_area_coord+igarea); 3873 gauss_coord[2]=*(third_gauss_area_coord+igarea); 3874 gauss_coord[3]=*(vert_gauss_coord+igvert); 3875 3876 /*Compute strain rate and viscosity: */ 3877 this->GetStrainRate3d(&epsilon[0],&xyz_list[0][0],gauss_coord,vx_input,vy_input,vz_input); 3878 matice->GetViscosity3dStokes(&viscosity,&epsilon[0]); 3879 3880 /* Get Jacobian determinant: */ 3881 GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss_coord); 3882 3883 /* Get nodal functions */ 3884 GetNodalFunctionsP1(&L[0], gauss_coord); 3885 3886 /*Build deformational heating: */ 3887 GetPhi(&phi, &epsilon[0], viscosity); 3888 3889 /*Build pe_gaussian */ 3890 scalar_def=phi/(rho_ice*heatcapacity)*Jdet*gauss_weight; 3891 if(dt){ 3892 scalar_def=scalar_def*dt; 3893 } 3894 3895 for(i=0;i<numgrids;i++){ 3896 P_terms[i]+=scalar_def*L[i]; 3897 } 3898 3899 /* Build transient now */ 3900 if(dt){ 3901 inputs->GetParameterValue(&temperature, gauss_coord,TemperatureEnum); 3902 scalar_transient=temperature*Jdet*gauss_weight; 3903 for(i=0;i<numgrids;i++){ 3904 P_terms[i]+=scalar_transient*L[i]; 3905 } 3906 } 3907 } 3908 } 3909 3910 /*Add pe_g to global vector pg: */ 3911 VecSetValues(pg,numdof,doflist,(const double*)P_terms,ADD_VALUES); 3912 3913 /* Ice/ocean heat exchange flux on ice shelf base */ 3914 if(onbed && shelf){ 3915 3916 tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria. 3917 tria->CreatePVectorThermalShelf(pg); 3918 delete tria; 3919 } 3920 3921 /* Geothermal flux on ice sheet base and basal friction */ 3922 if(onbed && !shelf){ 3923 3924 tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria. 3925 tria->CreatePVectorThermalSheet(pg); 3926 delete tria; 3927 } 3928 extern int my_rank; 3929 3930 xfree((void**)&first_gauss_area_coord); 3931 xfree((void**)&second_gauss_area_coord); 3932 xfree((void**)&third_gauss_area_coord); 3933 xfree((void**)&vert_gauss_coord); 3934 xfree((void**)&area_gauss_weights); 3935 xfree((void**)&vert_gauss_weights); 3936 2065 3937 } 2066 3938 /*}}}*/ … … 2104 3976 } 2105 3977 /*}}}*/ 3978 /*FUNCTION Penta::GetDofList {{{1*/ 3979 void Penta::GetDofList(int* doflist,int* pnumberofdofspernode){ 3980 3981 int i,j; 3982 int doflist_per_node[MAXDOFSPERNODE]; 3983 int numberofdofspernode; 3984 3985 for(i=0;i<6;i++){ 3986 nodes[i]->GetDofList(&doflist_per_node[0],&numberofdofspernode); 3987 for(j=0;j<numberofdofspernode;j++){ 3988 doflist[i*numberofdofspernode+j]=doflist_per_node[j]; 3989 } 3990 } 3991 3992 /*Assign output pointers:*/ 3993 *pnumberofdofspernode=numberofdofspernode; 3994 3995 } 3996 /*}}}*/ 3997 /*FUNCTION Penta::GetDofList1 {{{1*/ 3998 void Penta::GetDofList1(int* doflist){ 3999 4000 int i; 4001 4002 for(i=0;i<6;i++){ 4003 doflist[i]=nodes[i]->GetDofList1(); 4004 } 4005 4006 } 4007 /*}}}*/ 4008 /*FUNCTION Penta::GetElementType {{{1*/ 4009 int Penta::GetElementType(){ 4010 4011 /*return PentaRef field*/ 4012 return this->element_type; 4013 4014 } 4015 /*}}}*/ 4016 /*FUNCTION Penta::GetMatrixInvert {{{1*/ 4017 void Penta::GetMatrixInvert(double* Ke_invert, double* Ke){ 4018 /*Inverse a 3 by 3 matrix only */ 4019 4020 double a,b,c,d,e,f,g,h,i; 4021 double det; 4022 int calculationdof=3; 4023 4024 /*Take the matrix components: */ 4025 a=*(Ke+calculationdof*0+0); 4026 b=*(Ke+calculationdof*0+1); 4027 c=*(Ke+calculationdof*0+2); 4028 d=*(Ke+calculationdof*1+0); 4029 e=*(Ke+calculationdof*1+1); 4030 f=*(Ke+calculationdof*1+2); 4031 g=*(Ke+calculationdof*2+0); 4032 h=*(Ke+calculationdof*2+1); 4033 i=*(Ke+calculationdof*2+2); 4034 4035 det=a*(e*i-f*h)-b*(d*i-f*g)+c*(d*h-e*g); 4036 4037 *(Ke_invert+calculationdof*0+0)=(e*i-f*h)/det; 4038 *(Ke_invert+calculationdof*0+1)=(c*h-b*i)/det; 4039 *(Ke_invert+calculationdof*0+2)=(b*f-c*e)/det; 4040 *(Ke_invert+calculationdof*1+0)=(f*g-d*i)/det; 4041 *(Ke_invert+calculationdof*1+1)=(a*i-c*g)/det; 4042 *(Ke_invert+calculationdof*1+2)=(c*d-a*f)/det; 4043 *(Ke_invert+calculationdof*2+0)=(d*h-e*g)/det; 4044 *(Ke_invert+calculationdof*2+1)=(b*g-a*h)/det; 4045 *(Ke_invert+calculationdof*2+2)=(a*e-b*d)/det; 4046 4047 } 4048 /*}}}*/ 4049 /*FUNCTION Penta::GetParameterValue(double* pvalue, double* v_list,double* gauss_coord) {{{1*/ 4050 void Penta::GetParameterValue(double* pvalue, double* v_list,double* gauss_coord){ 4051 4052 const int numgrids=6; 4053 double l1l6[numgrids]; 4054 4055 GetNodalFunctionsP1(&l1l6[0], gauss_coord); 4056 4057 *pvalue=l1l6[0]*v_list[0]+l1l6[1]*v_list[1]+l1l6[2]*v_list[2]+l1l6[3]*v_list[3]+l1l6[4]*v_list[4]+l1l6[5]*v_list[5]; 4058 } 4059 /*}}}*/ 4060 /*FUNCTION Penta::GetParameterValue(double* pvalue,Node* node1,Node* node2,double gauss_seg,int enumtype) {{{1*/ 4061 void Penta::GetParameterValue(double* pvalue,Node* node,int enumtype){ 4062 4063 /*Output*/ 4064 double value; 4065 4066 /*Intermediaries*/ 4067 const int numnodes=6; 4068 int grid=-1; 4069 int i; 4070 double gauss[numnodes][4]={{1,0,0,-1},{0,1,0,-1},{0,0,1,-1},{1,0,0,1},{0,1,0,1},{0,0,1,1}}; 4071 4072 /*go through 3 nodes (all nodes for tria) and identify 1st and 2nd nodes: */ 4073 ISSMASSERT(nodes); 4074 for(i=0;i<numnodes;i++){ 4075 if (node==nodes[i]){ 4076 grid=i; 4077 break; 4078 } 4079 } 4080 4081 /*Check that the node has been found*/ 4082 if (grid==-1) ISSMERROR("Node pointer not found in Penta's nodes"); 4083 4084 /*Get Parameter value on node*/ 4085 inputs->GetParameterValue(pvalue,&gauss[grid][0],enumtype); 4086 return; 4087 4088 } 4089 /*}}}*/ 4090 /*FUNCTION Penta::GetPhi {{{1*/ 4091 void Penta::GetPhi(double* phi, double* epsilon, double viscosity){ 4092 /*Compute deformational heating from epsilon and viscosity */ 4093 4094 double epsilon_matrix[3][3]; 4095 double epsilon_eff; 4096 double epsilon_sqr[3][3]; 4097 4098 /* Build epsilon matrix */ 4099 epsilon_matrix[0][0]=*(epsilon+0); 4100 epsilon_matrix[1][0]=*(epsilon+3); 4101 epsilon_matrix[2][0]=*(epsilon+4); 4102 epsilon_matrix[0][1]=*(epsilon+3); 4103 epsilon_matrix[1][1]=*(epsilon+1); 4104 epsilon_matrix[2][1]=*(epsilon+5); 4105 epsilon_matrix[0][2]=*(epsilon+4); 4106 epsilon_matrix[1][2]=*(epsilon+5); 4107 epsilon_matrix[2][2]=*(epsilon+2); 4108 4109 /* Effective value of epsilon_matrix */ 4110 epsilon_sqr[0][0]=pow(epsilon_matrix[0][0],2); 4111 epsilon_sqr[1][0]=pow(epsilon_matrix[1][0],2); 4112 epsilon_sqr[2][0]=pow(epsilon_matrix[2][0],2); 4113 epsilon_sqr[0][1]=pow(epsilon_matrix[0][1],2); 4114 epsilon_sqr[1][1]=pow(epsilon_matrix[1][1],2); 4115 epsilon_sqr[2][1]=pow(epsilon_matrix[2][1],2); 4116 epsilon_sqr[0][2]=pow(epsilon_matrix[0][2],2); 4117 epsilon_sqr[1][2]=pow(epsilon_matrix[1][2],2); 4118 epsilon_sqr[2][2]=pow(epsilon_matrix[2][2],2); 4119 4120 epsilon_eff=1/pow(2,0.5)*pow((epsilon_sqr[0][0]+epsilon_sqr[0][1]+ epsilon_sqr[0][2]+ epsilon_sqr[1][0]+ epsilon_sqr[1][1]+ epsilon_sqr[1][2]+ epsilon_sqr[2][0]+ epsilon_sqr[2][1]+ epsilon_sqr[2][2]),0.5); 4121 *phi=2*pow(epsilon_eff,2.0)*viscosity; 4122 } 4123 /*}}}*/ 4124 /*FUNCTION Penta::GetSolutionFromInputsDiagnosticHoriz{{{1*/ 4125 void Penta::GetSolutionFromInputsDiagnosticHoriz(Vec solution){ 4126 4127 int i; 4128 4129 const int numvertices=6; 4130 const int numdofpervertex=2; 4131 const int numdof=numdofpervertex*numvertices; 4132 double gauss[numvertices][4]={{1,0,0,-1},{0,1,0,-1},{0,0,1,-1},{1,0,0,1},{0,1,0,1},{0,0,1,1}}; 4133 4134 int doflist[numdof]; 4135 double values[numdof]; 4136 double vx; 4137 double vy; 4138 4139 int dummy; 4140 4141 /*Get dof list: */ 4142 GetDofList(&doflist[0],&dummy); 4143 4144 /*Ok, we have vx and vy in values, fill in vx and vy arrays: */ 4145 /*P1 element only for now*/ 4146 for(i=0;i<numvertices;i++){ 4147 4148 /*Recover vx and vy*/ 4149 inputs->GetParameterValue(&vx,&gauss[i][0],VxEnum); 4150 inputs->GetParameterValue(&vy,&gauss[i][0],VyEnum); 4151 values[i*numdofpervertex+0]=vx; 4152 values[i*numdofpervertex+1]=vy; 4153 } 4154 4155 /*Add value to global vector*/ 4156 VecSetValues(solution,numdof,doflist,(const double*)values,INSERT_VALUES); 4157 4158 } 4159 /*}}}*/ 4160 /*FUNCTION Penta::GetSolutionFromInputsDiagnosticHutter{{{1*/ 4161 void Penta::GetSolutionFromInputsDiagnosticHutter(Vec solution){ 4162 4163 int i; 4164 4165 const int numvertices=6; 4166 const int numdofpervertex=2; 4167 const int numdof=numdofpervertex*numvertices; 4168 double gauss[numvertices][4]={{1,0,0,-1},{0,1,0,-1},{0,0,1,-1},{1,0,0,1},{0,1,0,1},{0,0,1,1}}; 4169 4170 int doflist[numdof]; 4171 double values[numdof]; 4172 double vx; 4173 double vy; 4174 4175 int dummy; 4176 4177 /*Get dof list: */ 4178 GetDofList(&doflist[0],&dummy); 4179 4180 /*Ok, we have vx and vy in values, fill in vx and vy arrays: */ 4181 /*P1 element only for now*/ 4182 for(i=0;i<numvertices;i++){ 4183 4184 /*Recover vx and vy*/ 4185 inputs->GetParameterValue(&vx,&gauss[i][0],VxEnum); 4186 inputs->GetParameterValue(&vy,&gauss[i][0],VyEnum); 4187 values[i*numdofpervertex+0]=vx; 4188 values[i*numdofpervertex+1]=vy; 4189 } 4190 4191 /*Add value to global vector*/ 4192 VecSetValues(solution,numdof,doflist,(const double*)values,INSERT_VALUES); 4193 4194 } 4195 /*}}}*/ 4196 /*FUNCTION Penta::GetSolutionFromInputsDiagnosticVert{{{1*/ 4197 void Penta::GetSolutionFromInputsDiagnosticVert(Vec solution){ 4198 4199 int i; 4200 4201 const int numvertices=6; 4202 const int numdofpervertex=1; 4203 const int numdof=numdofpervertex*numvertices; 4204 double gauss[numvertices][4]={{1,0,0,-1},{0,1,0,-1},{0,0,1,-1},{1,0,0,1},{0,1,0,1},{0,0,1,1}}; 4205 4206 int doflist[numdof]; 4207 double values[numdof]; 4208 double vz; 4209 4210 int dummy; 4211 4212 /*Get dof list: */ 4213 GetDofList(&doflist[0],&dummy); 4214 4215 /*Ok, we have vx and vy in values, fill in vx and vy arrays: */ 4216 /*P1 element only for now*/ 4217 for(i=0;i<numvertices;i++){ 4218 4219 /*Recover vz */ 4220 inputs->GetParameterValue(&vz,&gauss[i][0],VxEnum); 4221 values[i]=vz; 4222 } 4223 4224 /*Add value to global vector*/ 4225 VecSetValues(solution,numdof,doflist,(const double*)values,INSERT_VALUES); 4226 } 4227 /*}}}*/ 4228 /*FUNCTION Penta::GetSolutionFromInputsDiagnosticStokes{{{1*/ 4229 void Penta::GetSolutionFromInputsDiagnosticStokes(Vec solution){ 4230 4231 int i; 4232 4233 const int numvertices=6; 4234 const int numdofpervertex=4; 4235 const int numdof=numdofpervertex*numvertices; 4236 double gauss[numvertices][4]={{1,0,0,-1},{0,1,0,-1},{0,0,1,-1},{1,0,0,1},{0,1,0,1},{0,0,1,1}}; 4237 4238 int doflist[numdof]; 4239 double values[numdof]; 4240 double vx,vy,vz,p; 4241 4242 int dummy; 4243 double stokesreconditioning; 4244 4245 /*Get dof list: */ 4246 GetDofList(&doflist[0],&dummy); 4247 4248 /*Recondition pressure: */ 4249 this->parameters->FindParam(&stokesreconditioning,StokesReconditioningEnum); 4250 4251 /*Ok, we have vx vy vz and P in values, fill in vx vy vz P arrays: */ 4252 /*P1 element only for now*/ 4253 for(i=0;i<numvertices;i++){ 4254 4255 /*Recover vx and vy*/ 4256 inputs->GetParameterValue(&vx,&gauss[i][0],VxEnum); 4257 inputs->GetParameterValue(&vy,&gauss[i][0],VyEnum); 4258 inputs->GetParameterValue(&vz,&gauss[i][0],VzEnum); 4259 inputs->GetParameterValue(&p ,&gauss[i][0],PressureEnum); 4260 values[i*numdofpervertex+0]=vx; 4261 values[i*numdofpervertex+1]=vy; 4262 values[i*numdofpervertex+2]=vz; 4263 values[i*numdofpervertex+3]=p/stokesreconditioning; 4264 } 4265 4266 /*Add value to global vector*/ 4267 VecSetValues(solution,numdof,doflist,(const double*)values,INSERT_VALUES); 4268 4269 } 4270 /*}}}*/ 4271 /*FUNCTION Penta::GetSolutionFromInputsThermal{{{1*/ 4272 void Penta::GetSolutionFromInputsThermal(Vec solution){ 4273 4274 int i; 4275 4276 const int numvertices=6; 4277 const int numdofpervertex=1; 4278 const int numdof=numdofpervertex*numvertices; 4279 double gauss[numvertices][4]={{1,0,0,-1},{0,1,0,-1},{0,0,1,-1},{1,0,0,1},{0,1,0,1},{0,0,1,1}}; 4280 4281 int doflist[numdof]; 4282 double values[numdof]; 4283 double vz; 4284 4285 int dummy; 4286 4287 /*Get dof list: */ 4288 GetDofList(&doflist[0],&dummy); 4289 4290 /*Ok, we have vx and vy in values, fill in vx and vy arrays: */ 4291 /*P1 element only for now*/ 4292 for(i=0;i<numvertices;i++){ 4293 4294 /*Recover vz */ 4295 inputs->GetParameterValue(&vz,&gauss[i][0],TemperatureEnum); 4296 values[i]=vz; 4297 } 4298 4299 /*Add value to global vector*/ 4300 VecSetValues(solution,numdof,doflist,(const double*)values,INSERT_VALUES); 4301 } 4302 /*}}}*/ 4303 /*FUNCTION Penta::GetStrainRate3dPattyn{{{1*/ 4304 void Penta::GetStrainRate3dPattyn(double* epsilon,double* xyz_list, double* gauss, Input* vx_input, Input* vy_input){ 4305 /*Compute the 3d Blatter/PattynStrain Rate (5 components): 4306 * 4307 * epsilon=[exx eyy exy exz eyz] 4308 * 4309 * with exz=1/2 du/dz 4310 * eyz=1/2 dv/dz 4311 * 4312 * the contribution of vz is neglected 4313 */ 4314 4315 int i; 4316 4317 double epsilonvx[5]; 4318 double epsilonvy[5]; 4319 4320 /*Check that both inputs have been found*/ 4321 if (!vx_input || !vy_input){ 4322 ISSMERROR("Input missing. Here are the input pointers we have for vx: %p, vy: %p\n",vx_input,vy_input); 4323 } 4324 4325 /*Get strain rate assuming that epsilon has been allocated*/ 4326 vx_input->GetVxStrainRate3dPattyn(epsilonvx,xyz_list,gauss); 4327 vy_input->GetVyStrainRate3dPattyn(epsilonvy,xyz_list,gauss); 4328 4329 /*Sum all contributions*/ 4330 for(i=0;i<5;i++) epsilon[i]=epsilonvx[i]+epsilonvy[i]; 4331 4332 } 4333 /*}}}*/ 4334 /*FUNCTION Penta::GetStrainRate3d{{{1*/ 4335 void Penta::GetStrainRate3d(double* epsilon,double* xyz_list, double* gauss, Input* vx_input, Input* vy_input, Input* vz_input){ 4336 /*Compute the 3d Strain Rate (6 components): 4337 * 4338 * epsilon=[exx eyy ezz exy exz eyz] 4339 */ 4340 4341 int i; 4342 4343 double epsilonvx[6]; 4344 double epsilonvy[6]; 4345 double epsilonvz[6]; 4346 4347 /*Check that both inputs have been found*/ 4348 if (!vx_input || !vy_input || !vz_input){ 4349 ISSMERROR("Input missing. Here are the input pointers we have for vx: %p, vy: %p, vz: %p\n",vx_input,vy_input,vz_input); 4350 } 4351 4352 /*Get strain rate assuming that epsilon has been allocated*/ 4353 vx_input->GetVxStrainRate3d(epsilonvx,xyz_list,gauss); 4354 vy_input->GetVyStrainRate3d(epsilonvy,xyz_list,gauss); 4355 vz_input->GetVzStrainRate3d(epsilonvz,xyz_list,gauss); 4356 4357 /*Sum all contributions*/ 4358 for(i=0;i<6;i++) epsilon[i]=epsilonvx[i]+epsilonvy[i]+epsilonvz[i]; 4359 4360 } 4361 /*}}}*/ 4362 /*FUNCTION Penta::GetUpperElement{{{1*/ 4363 Penta* Penta::GetUpperElement(void){ 4364 4365 Penta* upper_penta=NULL; 4366 upper_penta=(Penta*)neighbors[1]; //first one under, second one above 4367 return upper_penta; 4368 4369 } 4370 /*}}}*/ 4371 /*FUNCTION Penta::GradjB {{{1*/ 4372 void Penta::GradjB(Vec gradient){ 4373 4374 int i; 4375 Tria* tria=NULL; 4376 TriaVertexInput* triavertexinput=NULL; 4377 4378 /*inputs: */ 4379 bool onwater; 4380 bool collapse; 4381 bool onbed; 4382 4383 /*retrieve inputs :*/ 4384 inputs->GetParameterValue(&onwater,ElementOnWaterEnum); 4385 inputs->GetParameterValue(&collapse,CollapseEnum); 4386 inputs->GetParameterValue(&onbed,ElementOnBedEnum); 4387 4388 /*If on water, skip: */ 4389 if(onwater)return; 4390 4391 if (collapse){ 4392 /*Bail out element if collapsed (2d) and not on bed*/ 4393 if (!onbed) return; 4394 4395 /*This element should be collapsed into a tria element at its base. Create this tria element, 4396 * and compute gardj*/ 4397 tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria (lower face). 4398 tria->GradjB(gradient); 4399 delete tria; 4400 } 4401 else{ 4402 /*B is a 2d field, use MacAyeal(2d) gradient even if it is Stokes or Pattyn*/ 4403 tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria (lower face). 4404 tria->GradjB(gradient); 4405 delete tria; 4406 } 4407 4408 4409 } 4410 /*}}}*/ 4411 /*FUNCTION Penta::GradjDrag {{{1*/ 4412 void Penta::GradjDrag(Vec gradient){ 4413 4414 int i; 4415 Tria* tria=NULL; 4416 TriaVertexInput* triavertexinput=NULL; 4417 double temp_gradient[6]={0,0,0,0,0,0}; 4418 4419 /*inputs: */ 4420 bool onwater; 4421 bool onbed; 4422 bool shelf; 4423 int analysis_type; 4424 4425 /*retrieve parameters: */ 4426 parameters->FindParam(&analysis_type,AnalysisTypeEnum); 4427 4428 /*retrieve inputs :*/ 4429 inputs->GetParameterValue(&onwater,ElementOnWaterEnum); 4430 inputs->GetParameterValue(&onbed,ElementOnBedEnum); 4431 inputs->GetParameterValue(&shelf,ElementOnIceShelfEnum); 4432 4433 /*If on water, skip: */ 4434 if(onwater)return; 4435 4436 /*If on shelf, skip: */ 4437 if(shelf)return; 4438 4439 /*Bail out if this element does not touch the bedrock: */ 4440 if (!onbed) return; 4441 4442 if (analysis_type==AdjointHorizAnalysisEnum){ 4443 4444 /*MacAyeal or Pattyn*/ 4445 tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria. 4446 tria->GradjDrag(gradient); 4447 delete tria; 4448 } 4449 else if (analysis_type==AdjointStokesAnalysisEnum){ 4450 4451 /*Stokes*/ 4452 tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria. 4453 tria->GradjDragStokes(gradient); 4454 delete tria; 4455 } 4456 else ISSMERROR("analysis %s not supported yet",EnumAsString(analysis_type)); 4457 4458 4459 } 4460 /*}}}*/ 4461 /*FUNCTION Penta::InputExtrude {{{1*/ 4462 void Penta::InputExtrude(int enum_type,bool only_if_collapsed){ 4463 4464 bool onbed,collapse=false; 4465 Penta *penta = NULL; 4466 Input *original_input = NULL; 4467 4468 /*recover parameters: */ 4469 if (only_if_collapsed) inputs->GetParameterValue(&collapse,CollapseEnum); 4470 inputs->GetParameterValue(&onbed,ElementOnBedEnum); 4471 4472 /*First: if only_if_collapsed, check wether this penta is collapsed*/ 4473 if (only_if_collapsed && !collapse) return; 4474 4475 /*Are we on the base, not on the surface?:*/ 4476 if(onbed){ 4477 4478 /*OK, we are on bed. we will follow the steps: 4479 * 1: find input and extrude it. 4480 * 2: follow the upper element until we reach the surface 4481 * 3: for each element, we will add a copy of the extruded input*/ 4482 4483 /*Step1: Extrude the original input: */ 4484 original_input=(Input*)this->inputs->GetInput(enum_type); 4485 if(!original_input) ISSMERROR("%s%s"," could not find input with enum:",EnumAsString(enum_type)); 4486 original_input->Extrude(); 4487 4488 /*Stop if there is only one layer of element*/ 4489 if (this->IsOnSurface()) return; 4490 4491 /*Step 2: this input has been extruded for this element, now follow the upper element*/ 4492 penta=this; 4493 for(;;){ 4494 4495 /* get upper Penta*/ 4496 penta=penta->GetUpperElement(); 4497 ISSMASSERT(penta->Id()!=this->id); 4498 4499 /*Add input of the basal element to penta->inputs*/ 4500 Input* copy=NULL; 4501 copy=(Input*)original_input->copy(); 4502 penta->inputs->AddInput((Input*)copy); 4503 4504 /*Stop if we have reached the surface*/ 4505 if (penta->IsOnSurface()) break; 4506 4507 } 4508 } 4509 4510 return; 4511 } 4512 /*}}}*/ 2106 4513 /*FUNCTION Penta::InputUpdateFromSolutionDiagnosticHoriz {{{1*/ 2107 4514 void Penta::InputUpdateFromSolutionDiagnosticHoriz(double* solution){ … … 2707 5114 penta=penta->GetUpperElement(); ISSMASSERT(penta->Id()!=this->id); 2708 5115 } 2709 }2710 /*}}}*/2711 /*FUNCTION Penta::GetSolutionFromInputsDiagnosticHoriz{{{1*/2712 void Penta::GetSolutionFromInputsDiagnosticHoriz(Vec solution){2713 2714 int i;2715 2716 const int numvertices=6;2717 const int numdofpervertex=2;2718 const int numdof=numdofpervertex*numvertices;2719 double gauss[numvertices][4]={{1,0,0,-1},{0,1,0,-1},{0,0,1,-1},{1,0,0,1},{0,1,0,1},{0,0,1,1}};2720 2721 int doflist[numdof];2722 double values[numdof];2723 double vx;2724 double vy;2725 2726 int dummy;2727 2728 /*Get dof list: */2729 GetDofList(&doflist[0],&dummy);2730 2731 /*Ok, we have vx and vy in values, fill in vx and vy arrays: */2732 /*P1 element only for now*/2733 for(i=0;i<numvertices;i++){2734 2735 /*Recover vx and vy*/2736 inputs->GetParameterValue(&vx,&gauss[i][0],VxEnum);2737 inputs->GetParameterValue(&vy,&gauss[i][0],VyEnum);2738 values[i*numdofpervertex+0]=vx;2739 values[i*numdofpervertex+1]=vy;2740 }2741 2742 /*Add value to global vector*/2743 VecSetValues(solution,numdof,doflist,(const double*)values,INSERT_VALUES);2744 2745 }2746 /*}}}*/2747 /*FUNCTION Penta::GetSolutionFromInputsDiagnosticHutter{{{1*/2748 void Penta::GetSolutionFromInputsDiagnosticHutter(Vec solution){2749 2750 int i;2751 2752 const int numvertices=6;2753 const int numdofpervertex=2;2754 const int numdof=numdofpervertex*numvertices;2755 double gauss[numvertices][4]={{1,0,0,-1},{0,1,0,-1},{0,0,1,-1},{1,0,0,1},{0,1,0,1},{0,0,1,1}};2756 2757 int doflist[numdof];2758 double values[numdof];2759 double vx;2760 double vy;2761 2762 int dummy;2763 2764 /*Get dof list: */2765 GetDofList(&doflist[0],&dummy);2766 2767 /*Ok, we have vx and vy in values, fill in vx and vy arrays: */2768 /*P1 element only for now*/2769 for(i=0;i<numvertices;i++){2770 2771 /*Recover vx and vy*/2772 inputs->GetParameterValue(&vx,&gauss[i][0],VxEnum);2773 inputs->GetParameterValue(&vy,&gauss[i][0],VyEnum);2774 values[i*numdofpervertex+0]=vx;2775 values[i*numdofpervertex+1]=vy;2776 }2777 2778 /*Add value to global vector*/2779 VecSetValues(solution,numdof,doflist,(const double*)values,INSERT_VALUES);2780 2781 }2782 /*}}}*/2783 /*FUNCTION Penta::GetSolutionFromInputsDiagnosticVert{{{1*/2784 void Penta::GetSolutionFromInputsDiagnosticVert(Vec solution){2785 2786 int i;2787 2788 const int numvertices=6;2789 const int numdofpervertex=1;2790 const int numdof=numdofpervertex*numvertices;2791 double gauss[numvertices][4]={{1,0,0,-1},{0,1,0,-1},{0,0,1,-1},{1,0,0,1},{0,1,0,1},{0,0,1,1}};2792 2793 int doflist[numdof];2794 double values[numdof];2795 double vz;2796 2797 int dummy;2798 2799 /*Get dof list: */2800 GetDofList(&doflist[0],&dummy);2801 2802 /*Ok, we have vx and vy in values, fill in vx and vy arrays: */2803 /*P1 element only for now*/2804 for(i=0;i<numvertices;i++){2805 2806 /*Recover vz */2807 inputs->GetParameterValue(&vz,&gauss[i][0],VxEnum);2808 values[i]=vz;2809 }2810 2811 /*Add value to global vector*/2812 VecSetValues(solution,numdof,doflist,(const double*)values,INSERT_VALUES);2813 }2814 /*}}}*/2815 /*FUNCTION Penta::GetSolutionFromInputsDiagnosticStokes{{{1*/2816 void Penta::GetSolutionFromInputsDiagnosticStokes(Vec solution){2817 2818 int i;2819 2820 const int numvertices=6;2821 const int numdofpervertex=4;2822 const int numdof=numdofpervertex*numvertices;2823 double gauss[numvertices][4]={{1,0,0,-1},{0,1,0,-1},{0,0,1,-1},{1,0,0,1},{0,1,0,1},{0,0,1,1}};2824 2825 int doflist[numdof];2826 double values[numdof];2827 double vx,vy,vz,p;2828 2829 int dummy;2830 double stokesreconditioning;2831 2832 /*Get dof list: */2833 GetDofList(&doflist[0],&dummy);2834 2835 /*Recondition pressure: */2836 this->parameters->FindParam(&stokesreconditioning,StokesReconditioningEnum);2837 2838 /*Ok, we have vx vy vz and P in values, fill in vx vy vz P arrays: */2839 /*P1 element only for now*/2840 for(i=0;i<numvertices;i++){2841 2842 /*Recover vx and vy*/2843 inputs->GetParameterValue(&vx,&gauss[i][0],VxEnum);2844 inputs->GetParameterValue(&vy,&gauss[i][0],VyEnum);2845 inputs->GetParameterValue(&vz,&gauss[i][0],VzEnum);2846 inputs->GetParameterValue(&p ,&gauss[i][0],PressureEnum);2847 values[i*numdofpervertex+0]=vx;2848 values[i*numdofpervertex+1]=vy;2849 values[i*numdofpervertex+2]=vz;2850 values[i*numdofpervertex+3]=p/stokesreconditioning;2851 }2852 2853 /*Add value to global vector*/2854 VecSetValues(solution,numdof,doflist,(const double*)values,INSERT_VALUES);2855 2856 }2857 /*}}}*/2858 /*FUNCTION Penta::GetSolutionFromInputsThermal{{{1*/2859 void Penta::GetSolutionFromInputsThermal(Vec solution){2860 2861 int i;2862 2863 const int numvertices=6;2864 const int numdofpervertex=1;2865 const int numdof=numdofpervertex*numvertices;2866 double gauss[numvertices][4]={{1,0,0,-1},{0,1,0,-1},{0,0,1,-1},{1,0,0,1},{0,1,0,1},{0,0,1,1}};2867 2868 int doflist[numdof];2869 double values[numdof];2870 double vz;2871 2872 int dummy;2873 2874 /*Get dof list: */2875 GetDofList(&doflist[0],&dummy);2876 2877 /*Ok, we have vx and vy in values, fill in vx and vy arrays: */2878 /*P1 element only for now*/2879 for(i=0;i<numvertices;i++){2880 2881 /*Recover vz */2882 inputs->GetParameterValue(&vz,&gauss[i][0],TemperatureEnum);2883 values[i]=vz;2884 }2885 2886 /*Add value to global vector*/2887 VecSetValues(solution,numdof,doflist,(const double*)values,INSERT_VALUES);2888 5116 } 2889 5117 /*}}}*/ … … 2926 5154 } 2927 5155 /*}}}*/ 2928 /*FUNCTION Penta::GetUpperElement{{{1*/2929 Penta* Penta::GetUpperElement(void){2930 2931 Penta* upper_penta=NULL;2932 upper_penta=(Penta*)neighbors[1]; //first one under, second one above2933 return upper_penta;2934 2935 }2936 /*}}}*/2937 /*FUNCTION Penta::CreateKMatrixBalancedthickness {{{1*/2938 2939 void Penta::CreateKMatrixBalancedthickness(Mat Kgg){2940 2941 /*Collapsed formulation: */2942 Tria* tria=NULL;2943 2944 /*flags: */2945 bool onwater;2946 bool onbed;2947 2948 /*recover some inputs: */2949 inputs->GetParameterValue(&onwater,ElementOnWaterEnum);2950 inputs->GetParameterValue(&onbed,ElementOnBedEnum);2951 2952 /*If on water, skip: */2953 if(onwater)return;2954 2955 /*Is this element on the bed? :*/2956 if(!onbed)return;2957 2958 /*Spawn Tria element from the base of the Penta: */2959 tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria.2960 tria->CreateKMatrix(Kgg);2961 delete tria;2962 return;2963 2964 }2965 /*}}}*/2966 /*FUNCTION Penta::CreateKMatrixBalancedvelocities {{{1*/2967 2968 void Penta::CreateKMatrixBalancedvelocities(Mat Kgg){2969 2970 /*Collapsed formulation: */2971 Tria* tria=NULL;2972 2973 /*flags: */2974 bool onbed;2975 bool onwater;2976 2977 /*recover some inputs: */2978 inputs->GetParameterValue(&onbed,ElementOnBedEnum);2979 inputs->GetParameterValue(&onwater,ElementOnWaterEnum);2980 2981 /*If on water, skip: */2982 if(onwater)return;2983 2984 /*Is this element on the bed? :*/2985 if(!onbed)return;2986 2987 /*Spawn Tria element from the base of the Penta: */2988 tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria.2989 tria->CreateKMatrix(Kgg);2990 delete tria;2991 return;2992 2993 }2994 /*}}}*/2995 /*FUNCTION Penta::CreateKMatrixDiagnosticHoriz {{{1*/2996 void Penta::CreateKMatrixDiagnosticHoriz( Mat Kgg){2997 2998 /* local declarations */2999 int i,j;3000 3001 /* node data: */3002 const int numgrids=6;3003 const int numdof=2*numgrids;3004 double xyz_list[numgrids][3];3005 int doflist[numdof];3006 int numberofdofspernode;3007 3008 /* 3d gaussian points: */3009 int num_gauss,ig;3010 double* first_gauss_area_coord = NULL;3011 double* second_gauss_area_coord = NULL;3012 double* third_gauss_area_coord = NULL;3013 double* fourth_gauss_vert_coord = NULL;3014 double* area_gauss_weights = NULL;3015 double* vert_gauss_weights = NULL;3016 int ig1,ig2;3017 double gauss_weight1,gauss_weight2;3018 double gauss_coord[4];3019 int order_area_gauss;3020 int num_vert_gauss;3021 int num_area_gauss;3022 double gauss_weight;3023 3024 /* 2d gaussian point: */3025 int num_gauss2d;3026 double* first_gauss_area_coord2d = NULL;3027 double* second_gauss_area_coord2d = NULL;3028 double* third_gauss_area_coord2d = NULL;3029 double* gauss_weights2d=NULL;3030 double gauss_l1l2l3[3];3031 3032 /* material data: */3033 double viscosity; //viscosity3034 double oldviscosity; //viscosity3035 double newviscosity; //viscosity3036 3037 /* strain rate: */3038 double epsilon[5]; /* epsilon=[exx,eyy,exy,exz,eyz];*/3039 double oldepsilon[5]; /* epsilon=[exx,eyy,exy,exz,eyz];*/3040 3041 /* matrices: */3042 double B[5][numdof];3043 double Bprime[5][numdof];3044 double L[2][numdof];3045 double D[5][5]={0.0}; // material matrix, simple scalar matrix.3046 double D_scalar;3047 double DL[2][2]={0.0}; //for basal drag3048 double DL_scalar;3049 3050 /* local element matrices: */3051 double Ke_gg[numdof][numdof]={0.0}; //local element stiffness matrix3052 3053 double Ke_gg_gaussian[numdof][numdof]; //stiffness matrix evaluated at the gaussian point.3054 double Ke_gg_drag_gaussian[numdof][numdof]; //stiffness matrix contribution from drag3055 double Jdet;3056 3057 /*slope: */3058 double slope[2]={0.0};3059 double slope_magnitude;3060 3061 /*friction: */3062 double alpha2_list[3];3063 double alpha2;3064 3065 double MAXSLOPE=.06; // 6 %3066 double MOUNTAINKEXPONENT=10;3067 3068 /*parameters: */3069 double viscosity_overshoot;3070 3071 /*Collapsed formulation: */3072 Tria* tria=NULL;3073 3074 /*inputs: */3075 bool onwater;3076 bool collapse;3077 bool onbed;3078 bool shelf;3079 Input* vx_input=NULL;3080 Input* vy_input=NULL;3081 Input* vxold_input=NULL;3082 Input* vyold_input=NULL;3083 3084 /*retrieve inputs :*/3085 inputs->GetParameterValue(&onwater,ElementOnWaterEnum);3086 inputs->GetParameterValue(&collapse,CollapseEnum);3087 inputs->GetParameterValue(&onbed,ElementOnBedEnum);3088 inputs->GetParameterValue(&shelf,ElementOnIceShelfEnum);3089 3090 /*retrieve some parameters: */3091 this->parameters->FindParam(&viscosity_overshoot,ViscosityOvershootEnum);3092 3093 /*If on water, skip stiffness: */3094 if(onwater)return;3095 3096 /*Figure out if this pentaelem is collapsed. If so, then bailout, except if it is at the3097 bedrock, in which case we spawn a tria element using the 3 first grids, and use it to build3098 the stiffness matrix. */3099 3100 if ((collapse==1) && (onbed==0)){3101 /*This element should be collapsed, but this element is not on the bedrock, therefore all its3102 * dofs have already been frozen! Do nothing: */3103 return;3104 }3105 else if ((collapse==1) && (onbed==1)){3106 3107 /*This element should be collapsed into a tria element at its base. Create this tria element,3108 *and use its CreateKMatrix functionality to fill the global stiffness matrix: */3109 tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria.3110 tria->CreateKMatrix(Kgg);3111 delete tria;3112 return;3113 }3114 else{3115 3116 /*Implement standard penta element: */3117 3118 /* Get node coordinates and dof list: */3119 GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);3120 GetDofList(&doflist[0],&numberofdofspernode);3121 3122 /*Get gaussian points and weights. Penta is an extrusion of a Tria, we therefore3123 get tria gaussian points as well as segment gaussian points. For tria gaussian3124 points, order of integration is 2, because we need to integrate the product tB*D*B'3125 which is a polynomial of degree 3 (see GaussTria for more details). For segment gaussian3126 points, same deal, which yields 3 gaussian points.*/3127 3128 order_area_gauss=5;3129 num_vert_gauss=5;3130 3131 GaussPenta( &num_area_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &area_gauss_weights, &fourth_gauss_vert_coord,&vert_gauss_weights,order_area_gauss,num_vert_gauss);3132 3133 /*Retrieve all inputs we will be needing: */3134 vx_input=inputs->GetInput(VxEnum);3135 vy_input=inputs->GetInput(VyEnum);3136 vxold_input=inputs->GetInput(VxOldEnum);3137 vyold_input=inputs->GetInput(VyOldEnum);3138 3139 /* Start looping on the number of gaussian points: */3140 for (ig1=0; ig1<num_area_gauss; ig1++){3141 for (ig2=0; ig2<num_vert_gauss; ig2++){3142 3143 /*Pick up the gaussian point: */3144 gauss_weight1=*(area_gauss_weights+ig1);3145 gauss_weight2=*(vert_gauss_weights+ig2);3146 gauss_weight=gauss_weight1*gauss_weight2;3147 3148 3149 gauss_coord[0]=*(first_gauss_area_coord+ig1);3150 gauss_coord[1]=*(second_gauss_area_coord+ig1);3151 gauss_coord[2]=*(third_gauss_area_coord+ig1);3152 gauss_coord[3]=*(fourth_gauss_vert_coord+ig2);3153 3154 3155 /*Get strain rate from velocity: */3156 this->GetStrainRate3dPattyn(&epsilon[0],&xyz_list[0][0],gauss_coord,vx_input,vy_input);3157 this->GetStrainRate3dPattyn(&oldepsilon[0],&xyz_list[0][0],gauss_coord,vxold_input,vyold_input);3158 3159 /*Get viscosity: */3160 matice->GetViscosity3d(&viscosity, &epsilon[0]);3161 matice->GetViscosity3d(&oldviscosity, &oldepsilon[0]);3162 3163 /*Get B and Bprime matrices: */3164 GetB(&B[0][0], &xyz_list[0][0], gauss_coord);3165 GetBPrime(&Bprime[0][0], &xyz_list[0][0], gauss_coord);3166 3167 /* Get Jacobian determinant: */3168 GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss_coord);3169 3170 /*Build the D matrix: we plug the gaussian weight, the viscosity, and the jacobian determinant3171 onto this scalar matrix, so that we win some computational time: */3172 3173 newviscosity=viscosity+viscosity_overshoot*(viscosity-oldviscosity);3174 D_scalar=newviscosity*gauss_weight*Jdet;3175 for (i=0;i<5;i++){3176 D[i][i]=D_scalar;3177 }3178 3179 /* Do the triple product tB*D*Bprime: */3180 TripleMultiply( &B[0][0],5,numdof,1,3181 &D[0][0],5,5,0,3182 &Bprime[0][0],5,numdof,0,3183 &Ke_gg_gaussian[0][0],0);3184 3185 /* Add the Ke_gg_gaussian, and optionally Ke_gg_gaussian onto Ke_gg: */3186 for( i=0; i<numdof; i++){3187 for(j=0;j<numdof;j++){3188 Ke_gg[i][j]+=Ke_gg_gaussian[i][j];3189 }3190 }3191 } //for (ig2=0; ig2<num_vert_gauss; ig2++)3192 } //for (ig1=0; ig1<num_area_gauss; ig1++)3193 3194 3195 /*Add Ke_gg to global matrix Kgg: */3196 MatSetValues(Kgg,numdof,doflist,numdof,doflist,(const double*)Ke_gg,ADD_VALUES);3197 3198 //Deal with 2d friction at the bedrock interface3199 if((onbed && !shelf)){3200 3201 /*Build a tria element using the 3 grids of the base of the penta. Then use3202 * the tria functionality to build a friction stiffness matrix on these 33203 * grids: */3204 3205 tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria.3206 tria->CreateKMatrixDiagnosticHorizFriction(Kgg);3207 delete tria;3208 }3209 3210 }3211 3212 xfree((void**)&first_gauss_area_coord);3213 xfree((void**)&second_gauss_area_coord);3214 xfree((void**)&third_gauss_area_coord);3215 xfree((void**)&fourth_gauss_vert_coord);3216 xfree((void**)&area_gauss_weights);3217 xfree((void**)&vert_gauss_weights);3218 xfree((void**)&first_gauss_area_coord2d);3219 xfree((void**)&second_gauss_area_coord2d);3220 xfree((void**)&third_gauss_area_coord2d);3221 xfree((void**)&gauss_weights2d);3222 3223 }3224 /*}}}*/3225 /*FUNCTION Penta::CreateKMatrixDiagnosticHutter{{{1*/3226 void Penta::CreateKMatrixDiagnosticHutter(Mat Kgg){3227 3228 /*Collapsed formulation: */3229 Beam* beam=NULL;3230 int i;3231 3232 /*flags: */3233 bool onwater;3234 3235 /*recover some inputs: */3236 inputs->GetParameterValue(&onwater,ElementOnWaterEnum);3237 3238 /*If on water, skip: */3239 if(onwater)return;3240 3241 /*Spawn 3 beam elements: */3242 for(i=0;i<3;i++){3243 beam=(Beam*)SpawnBeam(i,i+3); //[0 3], [1 4] and [2 5] are the four vertical edges of the Penta3244 beam->CreateKMatrix(Kgg);3245 }3246 3247 /*clean up*/3248 delete beam;3249 3250 }3251 /*}}}*/3252 /*FUNCTION Penta::CreateKMatrixDiagnosticStokes {{{1*/3253 void Penta::CreateKMatrixDiagnosticStokes( Mat Kgg){3254 3255 int i,j;3256 3257 const int numgrids=6;3258 const int DOFPERGRID=4;3259 const int numdof=numgrids*DOFPERGRID;3260 int doflist[numdof];3261 int numberofdofspernode;3262 3263 const int numgrids2d=3;3264 const int numdof2d=numgrids2d*DOFPERGRID;3265 3266 int dofs[3]={0,1,2};3267 3268 double K_terms[numdof][numdof]={0.0};3269 3270 /*Material properties: */3271 double gravity,rho_ice,rho_water;3272 3273 /*Collapsed formulation: */3274 Tria* tria=NULL;3275 3276 /*Grid data: */3277 double xyz_list[numgrids][3];3278 3279 /*parameters: */3280 double xyz_list_tria[numgrids2d][3];3281 double surface_normal[3];3282 double bed_normal[3];3283 double thickness;3284 3285 /*matrices: */3286 double Ke_temp[27][27]={0.0}; //for the six nodes and the bubble3287 double Ke_reduced[numdof][numdof]; //for the six nodes only3288 double Ke_gaussian[27][27];3289 double Ke_drag_gaussian[numdof2d][numdof2d];3290 double B[8][27];3291 double B_prime[8][27];3292 double LStokes[14][numdof2d];3293 double LprimeStokes[14][numdof2d];3294 double Jdet;3295 double Jdet2d;3296 double D[8][8]={0.0};3297 double D_scalar;3298 double tBD[27][8];3299 double DLStokes[14][14]={0.0};3300 double tLDStokes[numdof2d][14];3301 3302 /* gaussian points: */3303 int num_area_gauss;3304 int igarea,igvert;3305 double* first_gauss_area_coord = NULL;3306 double* second_gauss_area_coord = NULL;3307 double* third_gauss_area_coord = NULL;3308 double* vert_gauss_coord = NULL;3309 double* area_gauss_weights = NULL;3310 double* vert_gauss_weights = NULL;3311 double gaussgrids[numgrids][4]={{1,0,0,-1},{0,1,0,-1},{0,0,1,-1},{1,0,0,1},{0,1,0,1},{0,0,1,1}};3312 3313 /* specific gaussian point: */3314 double gauss_weight,area_gauss_weight,vert_gauss_weight;3315 double gauss_coord[4];3316 double gauss_coord_tria[3];3317 int area_order=5;3318 int num_vert_gauss=5;3319 3320 double epsilon[6]; /* epsilon=[exx,eyy,ezz,exy,exz,eyz];*/3321 double viscosity;3322 double alpha2_gauss;3323 Friction* friction=NULL;3324 3325 /*parameters: */3326 double stokesreconditioning;3327 int analysis_type;3328 3329 /*inputs: */3330 bool onwater;3331 bool onbed;3332 bool shelf;3333 bool isstokes;3334 3335 /*inputs: */3336 Input* vx_input=NULL;3337 Input* vy_input=NULL;3338 Input* vz_input=NULL;3339 3340 /*retrive parameters: */3341 parameters->FindParam(&analysis_type,AnalysisTypeEnum);3342 3343 /*retrieve inputs :*/3344 inputs->GetParameterValue(&onwater,ElementOnWaterEnum);3345 inputs->GetParameterValue(&onbed,ElementOnBedEnum);3346 inputs->GetParameterValue(&shelf,ElementOnIceShelfEnum);3347 inputs->GetParameterValue(&isstokes,IsStokesEnum);3348 3349 /*If on water or not Stokes, skip stiffness: */3350 if(onwater || !isstokes) return;3351 3352 /*recovre material parameters: */3353 rho_water=matpar->GetRhoWater();3354 rho_ice=matpar->GetRhoIce();3355 gravity=matpar->GetG();3356 3357 /*retrieve some parameters: */3358 this->parameters->FindParam(&stokesreconditioning,StokesReconditioningEnum);3359 3360 /* Get node coordinates and dof list: */3361 GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);3362 GetDofList(&doflist[0],&numberofdofspernode);3363 3364 /* Get gaussian points and weights. Penta is an extrusion of a Tria, we therefore3365 get tria gaussian points as well as segment gaussian points. For tria gaussian3366 points, order of integration is 2, because we need to integrate the product tB*D*B'3367 which is a polynomial of degree 3 (see GaussTria for more details). For segment gaussian3368 points, same deal, which yields 3 gaussian points.*/3369 3370 area_order=5;3371 num_vert_gauss=5;3372 3373 /* Get gaussian points and weights (make this a statically initialized list of points? fstd): */3374 GaussPenta( &num_area_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &area_gauss_weights,&vert_gauss_coord, &vert_gauss_weights, area_order, num_vert_gauss);3375 3376 /*Retrieve all inputs we will be needing: */3377 vx_input=inputs->GetInput(VxEnum);3378 vy_input=inputs->GetInput(VyEnum);3379 vz_input=inputs->GetInput(VzEnum);3380 3381 /* Start looping on the number of gaussian points: */3382 for (igarea=0; igarea<num_area_gauss; igarea++){3383 for (igvert=0; igvert<num_vert_gauss; igvert++){3384 /*Pick up the gaussian point: */3385 area_gauss_weight=*(area_gauss_weights+igarea);3386 vert_gauss_weight=*(vert_gauss_weights+igvert);3387 gauss_weight=area_gauss_weight*vert_gauss_weight;3388 gauss_coord[0]=*(first_gauss_area_coord+igarea);3389 gauss_coord[1]=*(second_gauss_area_coord+igarea);3390 gauss_coord[2]=*(third_gauss_area_coord+igarea);3391 gauss_coord[3]=*(vert_gauss_coord+igvert);3392 3393 /*Compute strain rate: */3394 this->GetStrainRate3d(&epsilon[0],&xyz_list[0][0],gauss_coord,vx_input,vy_input,vz_input);3395 3396 /*Get viscosity: */3397 matice->GetViscosity3dStokes(&viscosity,&epsilon[0]);3398 3399 /*Get B and Bprime matrices: */3400 GetBStokes(&B[0][0],&xyz_list[0][0],gauss_coord);3401 GetBprimeStokes(&B_prime[0][0],&xyz_list[0][0], gauss_coord);3402 3403 /* Get Jacobian determinant: */3404 GetJacobianDeterminant(&Jdet, &xyz_list[0][0],&gauss_coord[0]);3405 3406 /* Build the D matrix: we plug the gaussian weight, the thickness, the viscosity, and the jacobian determinant3407 * onto this scalar matrix, so that we win some computational time: */3408 D_scalar=gauss_weight*Jdet;3409 for (i=0;i<6;i++){3410 D[i][i]=D_scalar*viscosity;3411 }3412 for (i=6;i<8;i++){3413 D[i][i]=-D_scalar*stokesreconditioning;3414 }3415 3416 /* Do the triple product tB*D*Bprime: */3417 MatrixMultiply(&B[0][0],8,27,1,&D[0][0],8,8,0,&tBD[0][0],0);3418 MatrixMultiply(&tBD[0][0],27,8,0,&B_prime[0][0],8,27,0,&Ke_gaussian[0][0],0);3419 3420 /*Add Ke_gaussian and Ke_gaussian to terms in pKe. Watch out for column orientation from matlab: */3421 for(i=0;i<27;i++){3422 for(j=0;j<27;j++){3423 Ke_temp[i][j]+=Ke_gaussian[i][j];3424 }3425 }3426 }3427 }3428 3429 if((onbed==1) && (shelf==0)){3430 3431 /*build friction object, used later on: */3432 friction=new Friction("3d",inputs,matpar,analysis_type);3433 3434 for(i=0;i<numgrids2d;i++){3435 for(j=0;j<3;j++){3436 xyz_list_tria[i][j]=xyz_list[i][j];3437 }3438 }3439 3440 xfree((void**)&first_gauss_area_coord); xfree((void**)&second_gauss_area_coord); xfree((void**)&third_gauss_area_coord); xfree((void**)&area_gauss_weights);3441 GaussTria (&num_area_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &area_gauss_weights, 2);3442 3443 /* Start looping on the number of gauss 2d (nodes on the bedrock) */3444 for (igarea=0; igarea<num_area_gauss; igarea++){3445 gauss_weight=*(area_gauss_weights+igarea);3446 gauss_coord[0]=*(first_gauss_area_coord+igarea);3447 gauss_coord[1]=*(second_gauss_area_coord+igarea);3448 gauss_coord[2]=*(third_gauss_area_coord+igarea);3449 gauss_coord[3]=-1;3450 3451 gauss_coord_tria[0]=*(first_gauss_area_coord+igarea);3452 gauss_coord_tria[1]=*(second_gauss_area_coord+igarea);3453 gauss_coord_tria[2]=*(third_gauss_area_coord+igarea);3454 3455 /*Get the Jacobian determinant */3456 tria->GetJacobianDeterminant3d(&Jdet2d, &xyz_list_tria[0][0], gauss_coord_tria);3457 3458 /*Get L matrix if viscous basal drag present: */3459 GetLStokes(&LStokes[0][0], gauss_coord_tria);3460 GetLprimeStokes(&LprimeStokes[0][0], &xyz_list[0][0], gauss_coord_tria, gauss_coord);3461 3462 /*Compute strain rate: */3463 this->GetStrainRate3d(&epsilon[0],&xyz_list[0][0],gauss_coord,vx_input,vy_input,vz_input);3464 3465 /*Get viscosity at last iteration: */3466 matice->GetViscosity3dStokes(&viscosity,&epsilon[0]);3467 3468 /*Get normal vecyor to the bed */3469 SurfaceNormal(&surface_normal[0],xyz_list_tria);3470 3471 bed_normal[0]=-surface_normal[0]; //Program is for surface, so the normal to the bed is the opposite of the result3472 bed_normal[1]=-surface_normal[1];3473 bed_normal[2]=-surface_normal[2];3474 3475 /*Calculate DL on gauss point */3476 friction->GetAlpha2(&alpha2_gauss, gauss_coord,VxEnum,VyEnum,VzEnum);3477 3478 DLStokes[0][0]=alpha2_gauss*gauss_weight*Jdet2d;3479 DLStokes[1][1]=alpha2_gauss*gauss_weight*Jdet2d;3480 DLStokes[2][2]=-alpha2_gauss*gauss_weight*Jdet2d*bed_normal[0]*bed_normal[2];3481 DLStokes[3][3]=-alpha2_gauss*gauss_weight*Jdet2d*bed_normal[1]*bed_normal[2];3482 DLStokes[4][4]=-alpha2_gauss*gauss_weight*Jdet2d*bed_normal[0]*bed_normal[2];3483 DLStokes[5][5]=-alpha2_gauss*gauss_weight*Jdet2d*bed_normal[1]*bed_normal[2];3484 DLStokes[6][6]=-viscosity*gauss_weight*Jdet2d*bed_normal[0];3485 DLStokes[7][7]=-viscosity*gauss_weight*Jdet2d*bed_normal[1];3486 DLStokes[8][8]=-viscosity*gauss_weight*Jdet2d*bed_normal[2];3487 DLStokes[9][8]=-viscosity*gauss_weight*Jdet2d*bed_normal[0]/2.0;3488 DLStokes[10][10]=-viscosity*gauss_weight*Jdet2d*bed_normal[1]/2.0;3489 DLStokes[11][11]=stokesreconditioning*gauss_weight*Jdet2d*bed_normal[0];3490 DLStokes[12][12]=stokesreconditioning*gauss_weight*Jdet2d*bed_normal[1];3491 DLStokes[13][13]=stokesreconditioning*gauss_weight*Jdet2d*bed_normal[2];3492 3493 /* Do the triple product tL*D*L: */3494 MatrixMultiply(&LStokes[0][0],14,numdof2d,1,&DLStokes[0][0],14,14,0,&tLDStokes[0][0],0);3495 MatrixMultiply(&tLDStokes[0][0],numdof2d,14,0,&LprimeStokes[0][0],14,numdof2d,0,&Ke_drag_gaussian[0][0],0);3496 3497 for(i=0;i<numdof2d;i++){3498 for(j=0;j<numdof2d;j++){3499 Ke_temp[i][j]+=Ke_drag_gaussian[i][j];3500 }3501 }3502 }3503 3504 /*Free ressources:*/3505 delete friction;3506 3507 } //if ( (onbed==1) && (shelf==0))3508 3509 /*Reduce the matrix */3510 ReduceMatrixStokes(&Ke_reduced[0][0], &Ke_temp[0][0]);3511 3512 for(i=0;i<numdof;i++){3513 for(j=0;j<numdof;j++){3514 K_terms[i][j]+=Ke_reduced[i][j];3515 }3516 }3517 3518 /*Add Ke_gg to global matrix Kgg: */3519 MatSetValues(Kgg,numdof,doflist,numdof,doflist,(const double*)K_terms,ADD_VALUES);3520 3521 3522 /*Free ressources:*/3523 xfree((void**)&first_gauss_area_coord);3524 xfree((void**)&second_gauss_area_coord);3525 xfree((void**)&third_gauss_area_coord);3526 xfree((void**)&area_gauss_weights);3527 xfree((void**)&vert_gauss_coord);3528 xfree((void**)&vert_gauss_weights);3529 3530 return;3531 }3532 /*}}}*/3533 /*FUNCTION Penta::CreateKMatrixDiagnosticVert {{{1*/3534 void Penta::CreateKMatrixDiagnosticVert( Mat Kgg){3535 3536 /* local declarations */3537 int i,j;3538 3539 /* node data: */3540 const int numgrids=6;3541 const int NDOF1=1;3542 const int numdof=NDOF1*numgrids;3543 double xyz_list[numgrids][3];3544 int doflist[numdof];3545 int numberofdofspernode;3546 3547 /* 3d gaussian points: */3548 int num_gauss,ig;3549 double* first_gauss_area_coord = NULL;3550 double* second_gauss_area_coord = NULL;3551 double* third_gauss_area_coord = NULL;3552 double* fourth_gauss_vert_coord = NULL;3553 double* area_gauss_weights = NULL;3554 double* vert_gauss_weights = NULL;3555 int ig1,ig2;3556 double gauss_weight1,gauss_weight2;3557 double gauss_coord[4];3558 int order_area_gauss;3559 int num_vert_gauss;3560 int num_area_gauss;3561 double gauss_weight;3562 3563 /* matrices: */3564 double Ke_gg[numdof][numdof]={0.0};3565 double Ke_gg_gaussian[numdof][numdof];3566 double Jdet;3567 double B[NDOF1][numgrids];3568 double Bprime[NDOF1][numgrids];3569 double DL_scalar;3570 3571 /*Collapsed formulation: */3572 Tria* tria=NULL;3573 3574 /*inputs: */3575 bool onwater;3576 bool onsurface;3577 3578 /*retrieve inputs :*/3579 inputs->GetParameterValue(&onwater,ElementOnWaterEnum);3580 inputs->GetParameterValue(&onsurface,ElementOnSurfaceEnum);3581 3582 /*If on water, skip stiffness: */3583 if(onwater)return;3584 3585 /*If this element is on the surface, we have a dynamic boundary condition that applies, as a stiffness3586 * matrix: */3587 if(onsurface){3588 tria=(Tria*)SpawnTria(3,4,5); //nodes 3,4 and 5 are on the surface3589 tria->CreateKMatrixDiagnosticSurfaceVert(Kgg);3590 delete tria;3591 }3592 3593 /*Now, onto the formulation for the vertical velocity: */3594 3595 /* Get node coordinates and dof list: */3596 GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);3597 GetDofList(&doflist[0],&numberofdofspernode);3598 3599 /*Get gaussian points and weights. Penta is an extrusion of a Tria, we therefore3600 get tria gaussian points as well as segment gaussian points. For tria gaussian3601 points, order of integration is 2, because we need to integrate the product tB*D*B'3602 which is a polynomial of degree 3 (see GaussTria for more details). For segment gaussian3603 points, same deal, which yields 3 gaussian points.*/3604 3605 order_area_gauss=2;3606 num_vert_gauss=2;3607 3608 GaussPenta( &num_area_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &area_gauss_weights, &fourth_gauss_vert_coord,&vert_gauss_weights,order_area_gauss,num_vert_gauss);3609 3610 /* Start looping on the number of gaussian points: */3611 for (ig1=0; ig1<num_area_gauss; ig1++){3612 for (ig2=0; ig2<num_vert_gauss; ig2++){3613 3614 /*Pick up the gaussian point: */3615 gauss_weight1=*(area_gauss_weights+ig1);3616 gauss_weight2=*(vert_gauss_weights+ig2);3617 gauss_weight=gauss_weight1*gauss_weight2;3618 3619 gauss_coord[0]=*(first_gauss_area_coord+ig1);3620 gauss_coord[1]=*(second_gauss_area_coord+ig1);3621 gauss_coord[2]=*(third_gauss_area_coord+ig1);3622 gauss_coord[3]=*(fourth_gauss_vert_coord+ig2);3623 3624 /*Get B and Bprime matrices: */3625 GetB_vert(&B[0][0], &xyz_list[0][0], gauss_coord);3626 GetBPrime_vert(&Bprime[0][0], &xyz_list[0][0], gauss_coord);3627 3628 /* Get Jacobian determinant: */3629 GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss_coord);3630 DL_scalar=gauss_weight*Jdet;3631 3632 /* Do the triple product tB*D*Bprime: */3633 TripleMultiply( &B[0][0],1,numgrids,1,3634 &DL_scalar,1,1,0,3635 &Bprime[0][0],1,numgrids,0,3636 &Ke_gg_gaussian[0][0],0);3637 3638 /* Add the Ke_gg_gaussian, and optionally Ke_gg_drag_gaussian onto Ke_gg: */3639 for( i=0; i<numdof; i++){3640 for(j=0;j<numdof;j++){3641 Ke_gg[i][j]+=Ke_gg_gaussian[i][j];3642 }3643 }3644 } //for (ig2=0; ig2<num_vert_gauss; ig2++)3645 } //for (ig1=0; ig1<num_area_gauss; ig1++)3646 3647 /*Add Ke_gg to global matrix Kgg: */3648 MatSetValues(Kgg,numdof,doflist,numdof,doflist,(const double*)Ke_gg,ADD_VALUES);3649 3650 xfree((void**)&first_gauss_area_coord);3651 xfree((void**)&second_gauss_area_coord);3652 xfree((void**)&third_gauss_area_coord);3653 xfree((void**)&fourth_gauss_vert_coord);3654 xfree((void**)&area_gauss_weights);3655 xfree((void**)&vert_gauss_weights);3656 }3657 /*}}}*/3658 /*FUNCTION Penta::CreateKMatrixMelting {{{1*/3659 void Penta::CreateKMatrixMelting(Mat Kgg){3660 3661 Tria* tria=NULL;3662 3663 /*inputs: */3664 bool onwater;3665 bool onbed;3666 3667 /*retrieve inputs :*/3668 inputs->GetParameterValue(&onwater,ElementOnWaterEnum);3669 inputs->GetParameterValue(&onbed,ElementOnBedEnum);3670 3671 /*If on water, skip: */3672 if(onwater)return;3673 3674 if (!onbed){3675 return;3676 }3677 else{3678 3679 tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria.3680 tria->CreateKMatrixMelting(Kgg);3681 delete tria;3682 return;3683 }3684 }3685 /*}}}*/3686 /*FUNCTION Penta::CreateKMatrixPrognostic {{{1*/3687 3688 void Penta::CreateKMatrixPrognostic(Mat Kgg){3689 3690 /*Collapsed formulation: */3691 Tria* tria=NULL;3692 3693 /*inputs: */3694 bool onwater;3695 bool onbed;3696 3697 /*retrieve inputs :*/3698 inputs->GetParameterValue(&onwater,ElementOnWaterEnum);3699 inputs->GetParameterValue(&onbed,ElementOnBedEnum);3700 3701 /*If on water, skip: */3702 if(onwater)return;3703 3704 /*Is this element on the bed? :*/3705 if(!onbed)return;3706 3707 /*Spawn Tria element from the base of the Penta: */3708 tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria.3709 tria->CreateKMatrix(Kgg);3710 delete tria;3711 return;3712 3713 }3714 /*}}}*/3715 /*FUNCTION Penta::CreateKMatrixSlope {{{1*/3716 3717 void Penta::CreateKMatrixSlope(Mat Kgg){3718 3719 /*Collapsed formulation: */3720 Tria* tria=NULL;3721 3722 /*inputs: */3723 bool onwater;3724 bool onbed;3725 3726 /*retrieve inputs :*/3727 inputs->GetParameterValue(&onwater,ElementOnWaterEnum);3728 inputs->GetParameterValue(&onbed,ElementOnBedEnum);3729 3730 3731 /*If on water, skip: */3732 if(onwater)return;3733 3734 /*Is this element on the bed? :*/3735 if(!onbed)return;3736 3737 /*Spawn Tria element from the base of the Penta: */3738 tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria.3739 tria->CreateKMatrix(Kgg);3740 delete tria;3741 return;3742 3743 }3744 /*}}}*/3745 /*FUNCTION Penta::CreateKMatrixThermal {{{1*/3746 void Penta::CreateKMatrixThermal(Mat Kgg){3747 3748 /* local declarations */3749 int i,j;3750 int found=0;3751 3752 /* node data: */3753 const int numgrids=6;3754 const int NDOF1=1;3755 const int numdof=NDOF1*numgrids;3756 double xyz_list[numgrids][3];3757 int doflist[numdof];3758 int numberofdofspernode;3759 3760 /* gaussian points: */3761 int num_area_gauss,igarea,igvert;3762 double* first_gauss_area_coord = NULL;3763 double* second_gauss_area_coord = NULL;3764 double* third_gauss_area_coord = NULL;3765 double* vert_gauss_coord = NULL;3766 double* area_gauss_weights = NULL;3767 double* vert_gauss_weights = NULL;3768 double gauss_weight,area_gauss_weight,vert_gauss_weight;3769 double gauss_coord[4];3770 double gauss_l1l2l3[3];3771 3772 int area_order=5;3773 int num_vert_gauss=5;3774 3775 int dofs[3]={0,1,2};3776 double K[2][2]={0.0};3777 3778 double u,v,w;3779 3780 /*matrices: */3781 double K_terms[numdof][numdof]={0.0};3782 double Ke_gaussian_conduct[numdof][numdof];3783 double Ke_gaussian_advec[numdof][numdof];3784 double Ke_gaussian_artdiff[numdof][numdof];3785 double Ke_gaussian_transient[numdof][numdof];3786 double B[3][numdof];3787 double Bprime[3][numdof];3788 double B_conduct[3][numdof];3789 double B_advec[3][numdof];3790 double B_artdiff[2][numdof];3791 double Bprime_advec[3][numdof];3792 double L[numdof];3793 double D_scalar;3794 double D[3][3];3795 double l1l2l3[3];3796 double tl1l2l3D[3];3797 double tBD[3][numdof];3798 double tBD_conduct[3][numdof];3799 double tBD_advec[3][numdof];3800 double tBD_artdiff[3][numdof];3801 double tLD[numdof];3802 3803 double Jdet;3804 3805 /*Material properties: */3806 double gravity,rho_ice,rho_water;3807 double heatcapacity,thermalconductivity;3808 double mixed_layer_capacity,thermal_exchange_velocity;3809 3810 /*parameters: */3811 double dt,epsvel;3812 bool artdiff;3813 3814 /*Collapsed formulation: */3815 Tria* tria=NULL;3816 3817 3818 /*inputs: */3819 bool onwater;3820 bool onbed;3821 bool shelf;3822 3823 /*retrieve inputs :*/3824 inputs->GetParameterValue(&onwater,ElementOnWaterEnum);3825 inputs->GetParameterValue(&onbed,ElementOnBedEnum);3826 inputs->GetParameterValue(&shelf,ElementOnIceShelfEnum);3827 3828 /*If on water, skip: */3829 if(onwater)return;3830 3831 /* Get node coordinates and dof list: */3832 GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);3833 GetDofList(&doflist[0],&numberofdofspernode);3834 3835 // /*recovre material parameters: */3836 rho_water=matpar->GetRhoWater();3837 rho_ice=matpar->GetRhoIce();3838 gravity=matpar->GetG();3839 heatcapacity=matpar->GetHeatCapacity();3840 thermalconductivity=matpar->GetThermalConductivity();3841 3842 /*retrieve some parameters: */3843 this->parameters->FindParam(&dt,DtEnum);3844 this->parameters->FindParam(&artdiff,ArtDiffEnum);3845 this->parameters->FindParam(&epsvel,EpsVelEnum);3846 3847 /* Get gaussian points and weights. Penta is an extrusion of a Tria, we therefore3848 get tria gaussian points as well as segment gaussian points. For tria gaussian3849 points, order of integration is 2, because we need to integrate the product tB*D*B'3850 which is a polynomial of degree 3 (see GaussTria for more details). For segment gaussian3851 points, same deal, which yields 3 gaussian points.: */3852 3853 /*Get gaussian points: */3854 area_order=2;3855 num_vert_gauss=2;3856 3857 GaussPenta( &num_area_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &area_gauss_weights,&vert_gauss_coord, &vert_gauss_weights, area_order, num_vert_gauss);3858 3859 /* Start looping on the number of gaussian points: */3860 for (igarea=0; igarea<num_area_gauss; igarea++){3861 for (igvert=0; igvert<num_vert_gauss; igvert++){3862 /*Pick up the gaussian point: */3863 area_gauss_weight=*(area_gauss_weights+igarea);3864 vert_gauss_weight=*(vert_gauss_weights+igvert);3865 gauss_weight=area_gauss_weight*vert_gauss_weight;3866 gauss_coord[0]=*(first_gauss_area_coord+igarea);3867 gauss_coord[1]=*(second_gauss_area_coord+igarea);3868 gauss_coord[2]=*(third_gauss_area_coord+igarea);3869 gauss_coord[3]=*(vert_gauss_coord+igvert);3870 3871 /* Get Jacobian determinant: */3872 GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss_coord);3873 3874 /*Conduction: */3875 3876 /*Get B_conduct matrix: */3877 GetB_conduct(&B_conduct[0][0],&xyz_list[0][0],gauss_coord);3878 3879 /*Build D: */3880 D_scalar=gauss_weight*Jdet*(thermalconductivity/(rho_ice*heatcapacity));3881 3882 if(dt){3883 D_scalar=D_scalar*dt;3884 }3885 3886 D[0][0]=D_scalar; D[0][1]=0; D[0][2]=0;3887 D[1][0]=0; D[1][1]=D_scalar; D[1][2]=0;3888 D[2][0]=0; D[2][1]=0; D[2][2]=D_scalar;3889 3890 /* Do the triple product B'*D*B: */3891 MatrixMultiply(&B_conduct[0][0],3,numdof,1,&D[0][0],3,3,0,&tBD_conduct[0][0],0);3892 MatrixMultiply(&tBD_conduct[0][0],numdof,3,0,&B_conduct[0][0],3,numdof,0,&Ke_gaussian_conduct[0][0],0);3893 3894 /*Advection: */3895 3896 /*Get B_advec and Bprime_advec matrices: */3897 GetB_advec(&B_advec[0][0],&xyz_list[0][0],gauss_coord);3898 GetBprime_advec(&Bprime_advec[0][0],&xyz_list[0][0],gauss_coord);3899 3900 //Build the D matrix3901 inputs->GetParameterValue(&u, gauss_coord,VxEnum);3902 inputs->GetParameterValue(&v, gauss_coord,VyEnum);3903 inputs->GetParameterValue(&w, gauss_coord,VzEnum);3904 3905 D_scalar=gauss_weight*Jdet;3906 3907 if(dt){3908 D_scalar=D_scalar*dt;3909 }3910 3911 D[0][0]=D_scalar*u;D[0][1]=0; D[0][2]=0;3912 D[1][0]=0; D[1][1]=D_scalar*v;D[1][2]=0;3913 D[2][0]=0; D[2][1]=0; D[2][2]=D_scalar*w;3914 3915 /* Do the triple product B'*D*Bprime: */3916 MatrixMultiply(&B_advec[0][0],3,numdof,1,&D[0][0],3,3,0,&tBD_advec[0][0],0);3917 MatrixMultiply(&tBD_advec[0][0],numdof,3,0,&Bprime_advec[0][0],3,numdof,0,&Ke_gaussian_advec[0][0],0);3918 3919 /*Transient: */3920 if(dt){3921 GetNodalFunctions(&L[0], gauss_coord);3922 D_scalar=gauss_weight*Jdet;3923 D_scalar=D_scalar;3924 3925 /* Do the triple product L'*D*L: */3926 MatrixMultiply(&L[0],numdof,1,0,&D_scalar,1,1,0,&tLD[0],0);3927 MatrixMultiply(&tLD[0],numdof,1,0,&L[0],1,numdof,0,&Ke_gaussian_transient[0][0],0);3928 }3929 else{3930 for(i=0;i<numdof;i++){3931 for(j=0;j<numdof;j++){3932 Ke_gaussian_transient[i][j]=0;3933 }3934 }3935 }3936 3937 /*Artifficial diffusivity*/3938 if(artdiff){3939 /*Build K: */3940 D_scalar=gauss_weight*Jdet/(pow(u,2)+pow(v,2)+epsvel);3941 if(dt){3942 D_scalar=D_scalar*dt;3943 }3944 K[0][0]=D_scalar*pow(u,2); K[0][1]=D_scalar*fabs(u)*fabs(v);3945 K[1][0]=D_scalar*fabs(u)*fabs(v);K[1][1]=D_scalar*pow(v,2);3946 3947 /*Get B_artdiff: */3948 GetB_artdiff(&B_artdiff[0][0],&xyz_list[0][0],gauss_coord);3949 3950 /* Do the triple product B'*K*B: */3951 MatrixMultiply(&B_artdiff[0][0],2,numdof,1,&K[0][0],2,2,0,&tBD_artdiff[0][0],0);3952 MatrixMultiply(&tBD_artdiff[0][0],numdof,2,0,&B_artdiff[0][0],2,numdof,0,&Ke_gaussian_artdiff[0][0],0);3953 }3954 else{3955 for(i=0;i<numdof;i++){3956 for(j=0;j<numdof;j++){3957 Ke_gaussian_artdiff[i][j]=0;3958 }3959 }3960 }3961 3962 /*Add Ke_gaussian to pKe: */3963 for(i=0;i<numdof;i++){3964 for(j=0;j<numdof;j++){3965 K_terms[i][j]+=Ke_gaussian_conduct[i][j]+Ke_gaussian_advec[i][j]+Ke_gaussian_transient[i][j]+Ke_gaussian_artdiff[i][j];3966 }3967 }3968 }3969 }3970 3971 /*Add Ke_gg to global matrix Kgg: */3972 MatSetValues(Kgg,numdof,doflist,numdof,doflist,(const double*)K_terms,ADD_VALUES);3973 3974 xfree((void**)&first_gauss_area_coord);3975 xfree((void**)&second_gauss_area_coord);3976 xfree((void**)&third_gauss_area_coord);3977 xfree((void**)&area_gauss_weights);3978 xfree((void**)&vert_gauss_weights);3979 xfree((void**)&vert_gauss_coord);3980 3981 //Ice/ocean heat exchange flux on ice shelf base3982 if(onbed && shelf){3983 3984 tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria.3985 tria->CreateKMatrixThermal(Kgg);3986 delete tria;3987 }3988 }3989 /*}}}*/3990 /*FUNCTION Penta::CreatePVectorBalancedthickness {{{1*/3991 void Penta::CreatePVectorBalancedthickness( Vec pg){3992 3993 /*Collapsed formulation: */3994 Tria* tria=NULL;3995 3996 /*flags: */3997 bool onbed;3998 bool onwater;3999 4000 /*recover some inputs: */4001 inputs->GetParameterValue(&onbed,ElementOnBedEnum);4002 inputs->GetParameterValue(&onwater,ElementOnWaterEnum);4003 4004 /*If on water, skip: */4005 if(onwater)return;4006 4007 /*Is this element on the bed? :*/4008 if(!onbed)return;4009 4010 /*Spawn Tria element from the base of the Penta: */4011 tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria.4012 tria->CreatePVector(pg);4013 delete tria;4014 return;4015 }4016 /*}}}*/4017 /*FUNCTION Penta::CreatePVectorBalancedvelocities {{{1*/4018 void Penta::CreatePVectorBalancedvelocities( Vec pg){4019 4020 /*Collapsed formulation: */4021 Tria* tria=NULL;4022 4023 /*flags: */4024 bool onbed;4025 bool onwater;4026 4027 /*recover some inputs: */4028 inputs->GetParameterValue(&onbed,ElementOnBedEnum);4029 inputs->GetParameterValue(&onwater,ElementOnWaterEnum);4030 4031 /*If on water, skip: */4032 if(onwater)return;4033 4034 /*Is this element on the bed? :*/4035 if(!onbed)return;4036 4037 /*Spawn Tria element from the base of the Penta: */4038 tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria.4039 tria->CreatePVector(pg);4040 delete tria;4041 return;4042 }4043 /*}}}*/4044 /*FUNCTION Penta::CreatePVectorDiagnosticHoriz {{{1*/4045 void Penta::CreatePVectorDiagnosticHoriz( Vec pg){4046 4047 int i,j;4048 4049 /* node data: */4050 const int numgrids=6;4051 const int NDOF2=2;4052 const int numdof=NDOF2*numgrids;4053 double xyz_list[numgrids][3];4054 int doflist[numdof];4055 int numberofdofspernode;4056 4057 /* parameters: */4058 double slope[3]; //do not put 2! this goes into GetParameterDerivativeValue, which addresses slope[3] also!4059 double driving_stress_baseline;4060 double thickness;4061 4062 /* gaussian points: */4063 int num_gauss,ig;4064 double* first_gauss_area_coord = NULL;4065 double* second_gauss_area_coord = NULL;4066 double* third_gauss_area_coord = NULL;4067 double* fourth_gauss_vert_coord = NULL;4068 double* area_gauss_weights = NULL;4069 double* vert_gauss_weights = NULL;4070 double gauss_coord[4];4071 int order_area_gauss;4072 int num_vert_gauss;4073 int num_area_gauss;4074 int ig1,ig2;4075 double gauss_weight1,gauss_weight2;4076 double gauss_weight;4077 4078 /* Jacobian: */4079 double Jdet;4080 4081 /*nodal functions: */4082 double l1l6[6];4083 4084 /*element vector at the gaussian points: */4085 double pe_g[numdof]={0.0};4086 double pe_g_gaussian[numdof];4087 4088 /*Spawning: */4089 Tria* tria=NULL;4090 4091 /*inputs: */4092 bool onwater;4093 bool collapse;4094 bool onbed;4095 Input* surface_input=NULL;4096 Input* thickness_input=NULL;4097 4098 /*retrieve inputs :*/4099 inputs->GetParameterValue(&onwater,ElementOnWaterEnum);4100 inputs->GetParameterValue(&collapse,CollapseEnum);4101 inputs->GetParameterValue(&onbed,ElementOnBedEnum);4102 4103 /*If on water, skip load: */4104 if(onwater)return;4105 4106 /*Figure out if this pentaelem is collapsed. If so, then bailout, except if it is at the4107 bedrock, in which case we spawn a tria element using the 3 first grids, and use it to build4108 the load vector. */4109 4110 if ((collapse==1) && (onbed==0)){4111 /*This element should be collapsed, but this element is not on the bedrock, therefore all its4112 * dofs have already been frozen! Do nothing: */4113 return;4114 }4115 else if ((collapse==1) && (onbed==1)){4116 4117 /*This element should be collapsed into a tria element at its base. Create this tria element,4118 *and use its CreatePVector functionality to return an elementary load vector: */4119 tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria.4120 tria->CreatePVector(pg);4121 delete tria;4122 return;4123 }4124 else{4125 4126 /*Implement standard penta element: */4127 4128 /* Get node coordinates and dof list: */4129 GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);4130 GetDofList(&doflist[0],&numberofdofspernode);4131 4132 /*Get gaussian points and weights :*/4133 order_area_gauss=2;4134 num_vert_gauss=3;4135 4136 GaussPenta( &num_area_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &area_gauss_weights, &fourth_gauss_vert_coord,&vert_gauss_weights,order_area_gauss,num_vert_gauss);4137 4138 /*Retrieve all inputs we will be needing: */4139 thickness_input=inputs->GetInput(ThicknessEnum);4140 surface_input=inputs->GetInput(SurfaceEnum);4141 4142 /* Start looping on the number of gaussian points: */4143 for (ig1=0; ig1<num_area_gauss; ig1++){4144 for (ig2=0; ig2<num_vert_gauss; ig2++){4145 4146 /*Pick up the gaussian point: */4147 gauss_weight1=*(area_gauss_weights+ig1);4148 gauss_weight2=*(vert_gauss_weights+ig2);4149 gauss_weight=gauss_weight1*gauss_weight2;4150 4151 gauss_coord[0]=*(first_gauss_area_coord+ig1);4152 gauss_coord[1]=*(second_gauss_area_coord+ig1);4153 gauss_coord[2]=*(third_gauss_area_coord+ig1);4154 gauss_coord[3]=*(fourth_gauss_vert_coord+ig2);4155 4156 /*Compute thickness at gaussian point: */4157 thickness_input->GetParameterValue(&thickness, gauss_coord);4158 4159 /*Compute slope at gaussian point: */4160 surface_input->GetParameterDerivativeValue(&slope[0],&xyz_list[0][0],gauss_coord);4161 4162 /* Get Jacobian determinant: */4163 GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss_coord);4164 4165 /*Get nodal functions: */4166 GetNodalFunctions(l1l6, gauss_coord);4167 4168 /*Compute driving stress: */4169 driving_stress_baseline=matpar->GetRhoIce()*matpar->GetG();4170 4171 /*Build pe_g_gaussian vector: */4172 for (i=0;i<numgrids;i++){4173 for (j=0;j<NDOF2;j++){4174 pe_g_gaussian[i*NDOF2+j]=-driving_stress_baseline*slope[j]*Jdet*gauss_weight*l1l6[i];4175 }4176 }4177 4178 /*Add pe_g_gaussian vector to pe_g: */4179 for( i=0; i<numdof; i++)pe_g[i]+=pe_g_gaussian[i];4180 4181 } //for (ig2=0; ig2<num_vert_gauss; ig2++)4182 } //for (ig1=0; ig1<num_area_gauss; ig1++)4183 4184 } //else if ((collapse==1) && (onbed==1))4185 4186 /*Add pe_g to global vector pg: */4187 VecSetValues(pg,numdof,doflist,(const double*)pe_g,ADD_VALUES);4188 4189 xfree((void**)&first_gauss_area_coord);4190 xfree((void**)&second_gauss_area_coord);4191 xfree((void**)&third_gauss_area_coord);4192 xfree((void**)&fourth_gauss_vert_coord);4193 xfree((void**)&area_gauss_weights);4194 xfree((void**)&vert_gauss_weights);4195 4196 }4197 /*}}}*/4198 /*FUNCTION Penta::CreatePVectorAdjointHoriz{{{1*/4199 void Penta::CreatePVectorAdjointHoriz(Vec p_g){4200 4201 int i;4202 Tria* tria=NULL;4203 4204 /*inputs: */4205 bool onwater;4206 bool collapse;4207 bool onsurface;4208 bool onbed;4209 4210 /*retrieve inputs :*/4211 inputs->GetParameterValue(&onwater,ElementOnWaterEnum);4212 inputs->GetParameterValue(&collapse,CollapseEnum);4213 inputs->GetParameterValue(&onbed,ElementOnBedEnum);4214 inputs->GetParameterValue(&onsurface,ElementOnSurfaceEnum);4215 4216 /*If on water, skip: */4217 if(onwater) return;4218 4219 /*Bail out if this element if:4220 * -> Non collapsed and not on the surface4221 * -> collapsed (2d model) and not on bed) */4222 if ((!collapse && !onsurface) || (collapse && !onbed)){4223 return;4224 }4225 else if (collapse){4226 4227 /*This element should be collapsed into a tria element at its base. Create this tria element,4228 * and compute pe_g*/4229 tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria (lower face).4230 tria->CreatePVectorAdjointHoriz(p_g);4231 delete tria;4232 return;4233 }4234 else{4235 4236 tria=(Tria*)SpawnTria(3,4,5); //grids 3, 4 and 5 make the new tria (upper face).4237 tria->CreatePVectorAdjointHoriz(p_g);4238 delete tria;4239 return;4240 }4241 }4242 /*}}}*/4243 /*FUNCTION Penta::CreatePVectorDiagnosticHutter{{{1*/4244 void Penta::CreatePVectorDiagnosticHutter(Vec pg){4245 4246 /*Collapsed formulation: */4247 Beam* beam=NULL;4248 int i;4249 4250 /*flags: */4251 bool onwater;4252 4253 /*recover some inputs: */4254 inputs->GetParameterValue(&onwater,ElementOnWaterEnum);4255 4256 /*If on water, skip: */4257 if(onwater)return;4258 4259 /*Spawn 3 beam elements: */4260 for(i=0;i<3;i++){4261 beam=(Beam*)SpawnBeam(i,i+3); //[0 3], [1 4] and [2 5] are the four vertical edges of the Penta4262 beam->CreatePVector(pg);4263 }4264 4265 /*clean up*/4266 delete beam;4267 4268 }4269 /*}}}*/4270 /*FUNCTION Penta::CreatePVectorDiagnosticStokes {{{1*/4271 void Penta::CreatePVectorDiagnosticStokes( Vec pg){4272 4273 /*indexing: */4274 int i,j;4275 4276 const int numgrids=6;4277 const int DOFPERGRID=4;4278 const int numdof=numgrids*DOFPERGRID;4279 const int numgrids2d=3;4280 int numdof2d=numgrids2d*DOFPERGRID;4281 int doflist[numdof];4282 int numberofdofspernode;4283 4284 /*Material properties: */4285 double gravity,rho_ice,rho_water;4286 4287 /*parameters: */4288 double xyz_list_tria[numgrids2d][3];4289 double xyz_list[numgrids][3];4290 double surface_normal[3];4291 double bed_normal[3];4292 double bed;4293 4294 /* gaussian points: */4295 int num_area_gauss;4296 int igarea,igvert;4297 double* first_gauss_area_coord = NULL;4298 double* second_gauss_area_coord = NULL;4299 double* third_gauss_area_coord = NULL;4300 double* vert_gauss_coord = NULL;4301 double* area_gauss_weights = NULL;4302 double* vert_gauss_weights = NULL;4303 4304 /* specific gaussian point: */4305 double gauss_weight,area_gauss_weight,vert_gauss_weight;4306 double gauss_coord[4];4307 double gauss_coord_tria[3];4308 4309 int area_order=5;4310 int num_vert_gauss=5;4311 4312 double epsilon[6]; /* epsilon=[exx,eyy,ezz,exy,exz,eyz];*/4313 double viscosity;4314 double water_pressure;4315 int dofs[3]={0,1,2};4316 4317 /*matrices: */4318 double Pe_temp[27]={0.0}; //for the six nodes and the bubble4319 double Pe_gaussian[27]={0.0}; //for the six nodes and the bubble4320 double Ke_temp[27][3]={0.0}; //for the six nodes and the bubble4321 double Pe_reduced[numdof]; //for the six nodes only4322 double Ke_gaussian[27][3];4323 double L[3]; //for the three nodes of the bed4324 double l1l7[7]; //for the six nodes and the bubble4325 double B[8][27];4326 double B_prime[8][27];4327 double B_prime_bubble[8][3];4328 double Jdet;4329 double Jdet2d;4330 double D[8][8]={0.0};4331 double D_scalar;4332 double tBD[27][8];4333 double P_terms[numdof]={0.0};4334 4335 Tria* tria=NULL;4336 4337 /*parameters: */4338 double stokesreconditioning;4339 4340 /*inputs: */4341 bool onwater;4342 bool onbed;4343 bool shelf;4344 bool isstokes;4345 Input* vx_input=NULL;4346 Input* vy_input=NULL;4347 Input* vz_input=NULL;4348 Input* bed_input=NULL;4349 4350 /*retrieve inputs :*/4351 inputs->GetParameterValue(&onwater,ElementOnWaterEnum);4352 inputs->GetParameterValue(&onbed,ElementOnBedEnum);4353 inputs->GetParameterValue(&shelf,ElementOnIceShelfEnum);4354 inputs->GetParameterValue(&isstokes,IsStokesEnum);4355 4356 /*retrieve some parameters: */4357 this->parameters->FindParam(&stokesreconditioning,StokesReconditioningEnum);4358 4359 /*If on water or not Stokes, skip load: */4360 if(onwater || !isstokes) return;4361 4362 /*If on water, skip load: */4363 if(onwater)return;4364 4365 /*recovre material parameters: */4366 rho_water=matpar->GetRhoWater();4367 rho_ice=matpar->GetRhoIce();4368 gravity=matpar->GetG();4369 4370 /* Get node coordinates and dof list: */4371 GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);4372 GetDofList(&doflist[0],&numberofdofspernode);4373 4374 /* Get gaussian points and weights. Penta is an extrusion of a Tria, we therefore4375 get tria gaussian points as well as segment gaussian points. For tria gaussian4376 points, order of integration is 2, because we need to integrate the product tB*D*B'4377 which is a polynomial of degree 3 (see GaussTria for more details). For segment gaussian4378 points, same deal, which yields 3 gaussian points.*/4379 4380 /* Get gaussian points and weights (make this a statically initialized list of points? fstd): */4381 GaussPenta( &num_area_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &area_gauss_weights,&vert_gauss_coord, &vert_gauss_weights, area_order, num_vert_gauss);4382 4383 /*Retrieve all inputs we will be needing: */4384 vx_input=inputs->GetInput(VxEnum);4385 vy_input=inputs->GetInput(VyEnum);4386 vz_input=inputs->GetInput(VzEnum);4387 bed_input=inputs->GetInput(BedEnum);4388 4389 /* Start looping on the number of gaussian points: */4390 for (igarea=0; igarea<num_area_gauss; igarea++){4391 for (igvert=0; igvert<num_vert_gauss; igvert++){4392 /*Pick up the gaussian point: */4393 area_gauss_weight=*(area_gauss_weights+igarea);4394 vert_gauss_weight=*(vert_gauss_weights+igvert);4395 gauss_weight=area_gauss_weight*vert_gauss_weight;4396 gauss_coord[0]=*(first_gauss_area_coord+igarea);4397 gauss_coord[1]=*(second_gauss_area_coord+igarea);4398 gauss_coord[2]=*(third_gauss_area_coord+igarea);4399 gauss_coord[3]=*(vert_gauss_coord+igvert);4400 4401 /*Compute strain rate and viscosity: */4402 this->GetStrainRate3d(&epsilon[0],&xyz_list[0][0],gauss_coord,vx_input,vy_input,vz_input);4403 matice->GetViscosity3dStokes(&viscosity,&epsilon[0]);4404 4405 /* Get Jacobian determinant: */4406 GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss_coord);4407 4408 /* Get nodal functions */4409 GetNodalFunctionsStokes(&l1l7[0], gauss_coord);4410 4411 /* Build gaussian vector */4412 for(i=0;i<numgrids+1;i++){4413 Pe_gaussian[i*DOFPERGRID+2]=-rho_ice*gravity*Jdet*gauss_weight*l1l7[i];4414 }4415 4416 /*Add Pe_gaussian to terms in Pe_temp. Watch out for column orientation from matlab: */4417 for(i=0;i<27;i++){4418 Pe_temp[i]+=Pe_gaussian[i];4419 }4420 4421 /*Get B and Bprime matrices: */4422 GetBStokes(&B[0][0],&xyz_list[0][0],gauss_coord);4423 GetBprimeStokes(&B_prime[0][0],&xyz_list[0][0], gauss_coord);4424 4425 /*Get bubble part of Bprime */4426 for(i=0;i<8;i++){4427 for(j=0;j<3;j++){4428 B_prime_bubble[i][j]=B_prime[i][j+24];4429 }4430 }4431 4432 /* Build the D matrix: we plug the gaussian weight, the thickness, the viscosity, and the jacobian determinant4433 * onto this scalar matrix, so that we win some computational time: */4434 D_scalar=gauss_weight*Jdet;4435 for (i=0;i<6;i++){4436 D[i][i]=D_scalar*viscosity;4437 }4438 for (i=6;i<8;i++){4439 D[i][i]=-D_scalar*stokesreconditioning;4440 }4441 4442 /* Do the triple product tB*D*Bprime: */4443 MatrixMultiply(&B[0][0],8,27,1,&D[0][0],8,8,0,&tBD[0][0],0);4444 MatrixMultiply(&tBD[0][0],27,8,0,&B_prime_bubble[0][0],8,3,0,&Ke_gaussian[0][0],0);4445 4446 /*Add Ke_gaussian and Ke_gaussian to terms in pKe. Watch out for column orientation from matlab: */4447 for(i=0;i<27;i++){4448 for(j=0;j<3;j++){4449 Ke_temp[i][j]+=Ke_gaussian[i][j];4450 }4451 }4452 }4453 }4454 4455 /*Deal with 2d friction at the bedrock interface: */4456 if ( (onbed==1) && (shelf==1)){4457 4458 for(i=0;i<numgrids2d;i++){4459 for(j=0;j<3;j++){4460 xyz_list_tria[i][j]=xyz_list[i][j];4461 }4462 }4463 4464 xfree((void**)&first_gauss_area_coord); xfree((void**)&second_gauss_area_coord); xfree((void**)&third_gauss_area_coord); xfree((void**)&area_gauss_weights);4465 GaussTria (&num_area_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &area_gauss_weights, 2);4466 4467 /* Start looping on the number of gauss 2d (nodes on the bedrock) */4468 for (igarea=0; igarea<num_area_gauss; igarea++){4469 gauss_weight=*(area_gauss_weights+igarea);4470 gauss_coord[0]=*(first_gauss_area_coord+igarea);4471 gauss_coord[1]=*(second_gauss_area_coord+igarea);4472 gauss_coord[2]=*(third_gauss_area_coord+igarea);4473 gauss_coord[3]=-1;4474 4475 gauss_coord_tria[0]=*(first_gauss_area_coord+igarea);4476 gauss_coord_tria[1]=*(second_gauss_area_coord+igarea);4477 gauss_coord_tria[2]=*(third_gauss_area_coord+igarea);4478 4479 /*Get the Jacobian determinant */4480 tria->GetJacobianDeterminant3d(&Jdet2d, &xyz_list_tria[0][0], gauss_coord_tria);4481 4482 /* Get bed at gaussian point */4483 bed_input->GetParameterValue(&bed, gauss_coord);4484 4485 /*Get L matrix : */4486 tria->GetL(&L[0], &xyz_list[0][0], gauss_coord_tria,1);4487 4488 /*Get water_pressure at gaussian point */4489 water_pressure=gravity*rho_water*bed;4490 4491 /*Get normal vecyor to the bed */4492 SurfaceNormal(&surface_normal[0],xyz_list_tria);4493 4494 bed_normal[0]=-surface_normal[0]; //Program is for surface, so the normal to the bed is the opposite of the result4495 bed_normal[1]=-surface_normal[1];4496 bed_normal[2]=-surface_normal[2];4497 4498 for(i=0;i<numgrids2d;i++){4499 for(j=0;j<3;j++){4500 Pe_temp[i*DOFPERGRID+j]+=water_pressure*gauss_weight*Jdet2d*L[i]*bed_normal[j];4501 }4502 }4503 }4504 } //if ( (onbed==1) && (shelf==1))4505 4506 /*Reduce the matrix */4507 ReduceVectorStokes(&Pe_reduced[0], &Ke_temp[0][0], &Pe_temp[0]);4508 4509 for(i=0;i<numdof;i++){4510 P_terms[i]+=Pe_reduced[i];4511 }4512 4513 /*Add P_terms to global vector pg: */4514 VecSetValues(pg,numdof,doflist,(const double*)P_terms,ADD_VALUES);4515 4516 /*Free ressources:*/4517 xfree((void**)&first_gauss_area_coord);4518 xfree((void**)&second_gauss_area_coord);4519 xfree((void**)&third_gauss_area_coord);4520 xfree((void**)&area_gauss_weights);4521 xfree((void**)&vert_gauss_coord);4522 xfree((void**)&vert_gauss_weights);4523 4524 }4525 /*}}}*/4526 /*FUNCTION Penta::CreatePVectorAdjointStokes{{{1*/4527 void Penta::CreatePVectorAdjointStokes(Vec p_g){4528 4529 int i;4530 Tria* tria=NULL;4531 4532 /*inputs: */4533 bool onwater;4534 bool onsurface;4535 4536 /*retrieve inputs :*/4537 inputs->GetParameterValue(&onwater,ElementOnWaterEnum);4538 inputs->GetParameterValue(&onsurface,ElementOnSurfaceEnum);4539 4540 /*If on water, skip: */4541 if(onwater || !onsurface)return;4542 4543 /*Call Tria's function*/4544 tria=(Tria*)SpawnTria(3,4,5); //grids 3, 4 and 5 make the new tria (upper face).4545 tria->CreatePVectorAdjointStokes(p_g);4546 delete tria;4547 return;4548 }4549 /*}}}*/4550 /*FUNCTION Penta::CreatePVectorDiagnosticVert {{{1*/4551 void Penta::CreatePVectorDiagnosticVert( Vec pg){4552 4553 int i;4554 4555 /* node data: */4556 const int numgrids=6;4557 const int NDOF1=1;4558 const int numdof=NDOF1*numgrids;4559 double xyz_list[numgrids][3];4560 int doflist[numdof];4561 int numberofdofspernode;4562 4563 /* gaussian points: */4564 int num_gauss,ig;4565 double* first_gauss_area_coord = NULL;4566 double* second_gauss_area_coord = NULL;4567 double* third_gauss_area_coord = NULL;4568 double* fourth_gauss_vert_coord = NULL;4569 double* area_gauss_weights = NULL;4570 double* vert_gauss_weights = NULL;4571 double gauss_coord[4];4572 int order_area_gauss;4573 int num_vert_gauss;4574 int num_area_gauss;4575 int ig1,ig2;4576 double gauss_weight1,gauss_weight2;4577 double gauss_weight;4578 4579 /* Jacobian: */4580 double Jdet;4581 4582 /*element vector at the gaussian points: */4583 double pe_g[numdof]={0.0};4584 double pe_g_gaussian[numdof];4585 double l1l6[6];4586 4587 /*Spawning: */4588 Tria* tria=NULL;4589 4590 /*input parameters for structural analysis (diagnostic): */4591 double du[3];4592 double dv[3];4593 double dudx,dvdy;4594 int dofs1[1]={0};4595 int dofs2[1]={1};4596 4597 /*inputs: */4598 bool onwater;4599 bool onbed;4600 Input* vx_input=NULL;4601 Input* vy_input=NULL;4602 4603 /*retrieve inputs :*/4604 inputs->GetParameterValue(&onwater,ElementOnWaterEnum);4605 inputs->GetParameterValue(&onbed,ElementOnBedEnum);4606 4607 /*If on water, skip: */4608 if(onwater)return;4609 4610 /*If we are on the bedrock, spawn a tria on the bedrock, and use it to build the4611 *diagnostic base vertical stifness: */4612 if(onbed){4613 tria=(Tria*)SpawnTria(0,1,2); //nodes 0, 1 and 2 are on the bedrock4614 tria->CreatePVectorDiagnosticBaseVert(pg);4615 delete tria;4616 }4617 4618 /*Now, handle the standard penta element: */4619 /* Get node coordinates and dof list: */4620 GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);4621 GetDofList(&doflist[0],&numberofdofspernode);4622 4623 /*Get gaussian points and weights :*/4624 order_area_gauss=2;4625 num_vert_gauss=2;4626 4627 GaussPenta( &num_area_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &area_gauss_weights, &fourth_gauss_vert_coord,&vert_gauss_weights,order_area_gauss,num_vert_gauss);4628 4629 /*Retrieve all inputs we will be needing: */4630 vx_input=inputs->GetInput(VxEnum);4631 vy_input=inputs->GetInput(VyEnum);4632 4633 /* Start looping on the number of gaussian points: */4634 for (ig1=0; ig1<num_area_gauss; ig1++){4635 for (ig2=0; ig2<num_vert_gauss; ig2++){4636 4637 /*Pick up the gaussian point: */4638 gauss_weight1=*(area_gauss_weights+ig1);4639 gauss_weight2=*(vert_gauss_weights+ig2);4640 gauss_weight=gauss_weight1*gauss_weight2;4641 4642 gauss_coord[0]=*(first_gauss_area_coord+ig1);4643 gauss_coord[1]=*(second_gauss_area_coord+ig1);4644 gauss_coord[2]=*(third_gauss_area_coord+ig1);4645 gauss_coord[3]=*(fourth_gauss_vert_coord+ig2);4646 4647 /*Get velocity derivative, with respect to x and y: */4648 4649 vx_input->GetParameterDerivativeValue(&du[0],&xyz_list[0][0],gauss_coord);4650 vy_input->GetParameterDerivativeValue(&dv[0],&xyz_list[0][0],gauss_coord);4651 dudx=du[0];4652 dvdy=dv[1];4653 4654 /* Get Jacobian determinant: */4655 GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss_coord);4656 4657 /*Get nodal functions: */4658 GetNodalFunctions(l1l6, gauss_coord);4659 4660 /*Build pe_g_gaussian vector: */4661 for (i=0;i<numgrids;i++){4662 pe_g_gaussian[i]=(dudx+dvdy)*Jdet*gauss_weight*l1l6[i];4663 }4664 4665 /*Add pe_g_gaussian vector to pe_g: */4666 for( i=0; i<numdof; i++)pe_g[i]+=pe_g_gaussian[i];4667 4668 } //for (ig2=0; ig2<num_vert_gauss; ig2++)4669 } //for (ig1=0; ig1<num_area_gauss; ig1++)4670 4671 /*Add pe_g to global vector pg: */4672 VecSetValues(pg,numdof,doflist,(const double*)pe_g,ADD_VALUES);4673 4674 xfree((void**)&first_gauss_area_coord);4675 xfree((void**)&second_gauss_area_coord);4676 xfree((void**)&third_gauss_area_coord);4677 xfree((void**)&fourth_gauss_vert_coord);4678 xfree((void**)&area_gauss_weights);4679 xfree((void**)&vert_gauss_weights);4680 }4681 /*}}}*/4682 /*FUNCTION Penta::CreatePVectorMelting {{{1*/4683 void Penta::CreatePVectorMelting( Vec pg){4684 return;4685 }4686 /*}}}*/4687 /*FUNCTION Penta::CreatePVectorPrognostic {{{1*/4688 4689 void Penta::CreatePVectorPrognostic( Vec pg){4690 4691 /*Collapsed formulation: */4692 Tria* tria=NULL;4693 4694 /*inputs: */4695 bool onwater;4696 bool onbed;4697 4698 /*retrieve inputs :*/4699 inputs->GetParameterValue(&onwater,ElementOnWaterEnum);4700 inputs->GetParameterValue(&onbed,ElementOnBedEnum);4701 4702 /*If on water, skip: */4703 if(onwater)return;4704 4705 /*Is this element on the bed? :*/4706 if(!onbed)return;4707 4708 /*Spawn Tria element from the base of the Penta: */4709 tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria.4710 tria->CreatePVector(pg);4711 delete tria;4712 return;4713 }4714 /*}}}*/4715 /*FUNCTION Penta::CreatePVectorSlope {{{1*/4716 4717 void Penta::CreatePVectorSlope( Vec pg){4718 4719 /*Collapsed formulation: */4720 Tria* tria=NULL;4721 4722 /*inputs: */4723 bool onwater;4724 bool onbed;4725 4726 /*retrieve inputs :*/4727 inputs->GetParameterValue(&onwater,ElementOnWaterEnum);4728 inputs->GetParameterValue(&onbed,ElementOnBedEnum);4729 4730 /*If on water, skip: */4731 if(onwater)return;4732 4733 /*Is this element on the bed? :*/4734 if(!onbed)return;4735 4736 /*Spawn Tria element from the base of the Penta: */4737 tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria.4738 tria->CreatePVector(pg);4739 delete tria;4740 return;4741 }4742 /*}}}*/4743 /*FUNCTION Penta::CreatePVectorThermal {{{1*/4744 void Penta::CreatePVectorThermal( Vec pg){4745 4746 /*indexing: */4747 int i,j;4748 int found=0;4749 4750 const int numgrids=6;4751 const int NDOF1=1;4752 const int numdof=numgrids*NDOF1;4753 int doflist[numdof];4754 int numberofdofspernode;4755 4756 /*Grid data: */4757 double xyz_list[numgrids][3];4758 4759 /* gaussian points: */4760 int num_area_gauss,igarea,igvert;4761 double* first_gauss_area_coord = NULL;4762 double* second_gauss_area_coord = NULL;4763 double* third_gauss_area_coord = NULL;4764 double* vert_gauss_coord = NULL;4765 double* area_gauss_weights = NULL;4766 double* vert_gauss_weights = NULL;4767 double gauss_weight,area_gauss_weight,vert_gauss_weight;4768 double gauss_coord[4];4769 int area_order=2;4770 int num_vert_gauss=3;4771 4772 double temperature_list[numgrids];4773 double temperature;4774 4775 /*Material properties: */4776 double gravity,rho_ice,rho_water;4777 double mixed_layer_capacity,heatcapacity;4778 double beta,meltingpoint,thermal_exchange_velocity;4779 4780 /* element parameters: */4781 int friction_type;4782 4783 int dofs[3]={0,1,2};4784 int dofs1[1]={0};4785 4786 /*matrices: */4787 double P_terms[numdof]={0.0};4788 double L[numdof];4789 double l1l2l3[3];4790 double alpha2_list[3];4791 double basalfriction_list[3]={0.0};4792 double basalfriction;4793 double epsilon[6];4794 double epsilon_sqr[3][3];4795 double epsilon_matrix[3][3];4796 4797 double Jdet;4798 double viscosity;4799 double epsilon_eff;4800 double phi;4801 double t_pmp;4802 double scalar;4803 double scalar_def;4804 double scalar_ocean;4805 double scalar_transient;4806 4807 /*Collapsed formulation: */4808 Tria* tria=NULL;4809 4810 /*parameters: */4811 double dt;4812 4813 /*inputs: */4814 bool onwater;4815 bool onbed;4816 bool shelf;4817 Input* vx_input=NULL;4818 Input* vy_input=NULL;4819 Input* vz_input=NULL;4820 4821 /*retrieve inputs :*/4822 inputs->GetParameterValue(&onwater,ElementOnWaterEnum);4823 inputs->GetParameterValue(&onbed,ElementOnBedEnum);4824 inputs->GetParameterValue(&shelf,ElementOnIceShelfEnum);4825 4826 /*retrieve some parameters: */4827 this->parameters->FindParam(&dt,DtEnum);4828 4829 /*If on water, skip: */4830 if(onwater)return;4831 4832 /* Get node coordinates and dof list: */4833 GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);4834 GetDofList(&doflist[0],&numberofdofspernode);4835 4836 /*recovre material parameters: */4837 rho_water=matpar->GetRhoWater();4838 rho_ice=matpar->GetRhoIce();4839 gravity=matpar->GetG();4840 heatcapacity=matpar->GetHeatCapacity();4841 beta=matpar->GetBeta();4842 meltingpoint=matpar->GetMeltingPoint();4843 4844 /* Get gaussian points and weights. Penta is an extrusion of a Tria, we therefore4845 get tria gaussian points as well as segment gaussian points. For tria gaussian4846 points, order of integration is 2, because we need to integrate the product tB*D*B'4847 which is a polynomial of degree 3 (see GaussTria for more details). For segment gaussian4848 points, same deal, which yields 3 gaussian points.: */4849 4850 /*Get gaussian points: */4851 GaussPenta( &num_area_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &area_gauss_weights,&vert_gauss_coord, &vert_gauss_weights, area_order, num_vert_gauss);4852 4853 /*Retrieve all inputs we will be needing: */4854 vx_input=inputs->GetInput(VxEnum);4855 vy_input=inputs->GetInput(VyEnum);4856 vz_input=inputs->GetInput(VzEnum);4857 4858 /* Start looping on the number of gaussian points: */4859 for (igarea=0; igarea<num_area_gauss; igarea++){4860 for (igvert=0; igvert<num_vert_gauss; igvert++){4861 /*Pick up the gaussian point: */4862 area_gauss_weight=*(area_gauss_weights+igarea);4863 vert_gauss_weight=*(vert_gauss_weights+igvert);4864 gauss_weight=area_gauss_weight*vert_gauss_weight;4865 gauss_coord[0]=*(first_gauss_area_coord+igarea);4866 gauss_coord[1]=*(second_gauss_area_coord+igarea);4867 gauss_coord[2]=*(third_gauss_area_coord+igarea);4868 gauss_coord[3]=*(vert_gauss_coord+igvert);4869 4870 /*Compute strain rate and viscosity: */4871 this->GetStrainRate3d(&epsilon[0],&xyz_list[0][0],gauss_coord,vx_input,vy_input,vz_input);4872 matice->GetViscosity3dStokes(&viscosity,&epsilon[0]);4873 4874 /* Get Jacobian determinant: */4875 GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss_coord);4876 4877 /* Get nodal functions */4878 GetNodalFunctions(&L[0], gauss_coord);4879 4880 /*Build deformational heating: */4881 GetPhi(&phi, &epsilon[0], viscosity);4882 4883 /*Build pe_gaussian */4884 scalar_def=phi/(rho_ice*heatcapacity)*Jdet*gauss_weight;4885 if(dt){4886 scalar_def=scalar_def*dt;4887 }4888 4889 for(i=0;i<numgrids;i++){4890 P_terms[i]+=scalar_def*L[i];4891 }4892 4893 /* Build transient now */4894 if(dt){4895 inputs->GetParameterValue(&temperature, gauss_coord,TemperatureEnum);4896 scalar_transient=temperature*Jdet*gauss_weight;4897 for(i=0;i<numgrids;i++){4898 P_terms[i]+=scalar_transient*L[i];4899 }4900 }4901 }4902 }4903 4904 /*Add pe_g to global vector pg: */4905 VecSetValues(pg,numdof,doflist,(const double*)P_terms,ADD_VALUES);4906 4907 /* Ice/ocean heat exchange flux on ice shelf base */4908 if(onbed && shelf){4909 4910 tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria.4911 tria->CreatePVectorThermalShelf(pg);4912 delete tria;4913 }4914 4915 /* Geothermal flux on ice sheet base and basal friction */4916 if(onbed && !shelf){4917 4918 tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria.4919 tria->CreatePVectorThermalSheet(pg);4920 delete tria;4921 }4922 extern int my_rank;4923 4924 xfree((void**)&first_gauss_area_coord);4925 xfree((void**)&second_gauss_area_coord);4926 xfree((void**)&third_gauss_area_coord);4927 xfree((void**)&vert_gauss_coord);4928 xfree((void**)&area_gauss_weights);4929 xfree((void**)&vert_gauss_weights);4930 4931 }4932 /*}}}*/4933 /*FUNCTION Penta::VecExtrude {{{1*/4934 void Penta::VecExtrude(Vec vector,double* vector_serial,int iscollapsed){4935 4936 /* node data: */4937 int i;4938 Node* node=NULL;4939 int extrude=0;4940 4941 /*inputs: */4942 bool collapse;4943 bool onbed;4944 4945 /*retrieve inputs :*/4946 inputs->GetParameterValue(&collapse,CollapseEnum);4947 inputs->GetParameterValue(&onbed,ElementOnBedEnum);4948 4949 /*Figure out if we should extrude for this element: */4950 if (iscollapsed){4951 /*From higher level, we are told to extrude only elements that have the collapse flag on: */4952 if (collapse)extrude=1;4953 else extrude=0;4954 }4955 else{4956 /*From higher level, we are told to extrude all elements: */4957 extrude=1;4958 }4959 4960 /*Now, extrusion starts from the bed on, so double check this element is on4961 * the bedrock: */4962 if(onbed==0)extrude=0;4963 4964 /*Go on and extrude vector: */4965 if (extrude){4966 4967 /* node data: */4968 int dof1;4969 double vectorel;4970 4971 /*this penta is a collapsed macayeal. For each node on the base of this penta,4972 * we grab the vector. Once we know the vector, we follow the upper nodes,4973 * inserting the same vector value into vector, until we reach the surface: */4974 for(i=0;i<3;i++){4975 4976 node=nodes[i]; //base nodes4977 dof1=node->GetDofList1();4978 4979 /*get vector for this base node: */4980 vectorel=vector_serial[dof1];4981 4982 //go throvectorn all nodes which sit on top of this node, until we reach the surface,4983 //and plvector vector in vector4984 for(;;){4985 4986 dof1=node->GetDofList1();4987 VecSetValues(vector,1,&dof1,&vectorel,INSERT_VALUES);4988 4989 if (node->IsOnSurface())break;4990 /*get next node: */4991 node=node->GetUpperNode();4992 }4993 }4994 }4995 }4996 /*}}}*/4997 /*FUNCTION Penta::InputExtrude {{{1*/4998 void Penta::InputExtrude(int enum_type,bool only_if_collapsed){4999 5000 bool onbed,collapse=false;5001 Penta *penta = NULL;5002 Input *original_input = NULL;5003 5004 /*recover parameters: */5005 if (only_if_collapsed) inputs->GetParameterValue(&collapse,CollapseEnum);5006 inputs->GetParameterValue(&onbed,ElementOnBedEnum);5007 5008 /*First: if only_if_collapsed, check wether this penta is collapsed*/5009 if (only_if_collapsed && !collapse) return;5010 5011 /*Are we on the base, not on the surface?:*/5012 if(onbed){5013 5014 /*OK, we are on bed. we will follow the steps:5015 * 1: find input and extrude it.5016 * 2: follow the upper element until we reach the surface5017 * 3: for each element, we will add a copy of the extruded input*/5018 5019 /*Step1: Extrude the original input: */5020 original_input=(Input*)this->inputs->GetInput(enum_type);5021 if(!original_input) ISSMERROR("%s%s"," could not find input with enum:",EnumAsString(enum_type));5022 original_input->Extrude();5023 5024 /*Stop if there is only one layer of element*/5025 if (this->IsOnSurface()) return;5026 5027 /*Step 2: this input has been extruded for this element, now follow the upper element*/5028 penta=this;5029 for(;;){5030 5031 /* get upper Penta*/5032 penta=penta->GetUpperElement();5033 ISSMASSERT(penta->Id()!=this->id);5034 5035 /*Add input of the basal element to penta->inputs*/5036 Input* copy=NULL;5037 copy=(Input*)original_input->copy();5038 penta->inputs->AddInput((Input*)copy);5039 5040 /*Stop if we have reached the surface*/5041 if (penta->IsOnSurface()) break;5042 5043 }5044 }5045 5046 return;5047 }5048 /*}}}*/5049 /*FUNCTION Penta::GetB {{{1*/5050 void Penta::GetB(double* B, double* xyz_list, double* gauss_coord){5051 5052 /*Compute B matrix. B=[B1 B2 B3 B4 B5 B6] where Bi is of size 5*NDOF2.5053 * For grid i, Bi can be expressed in the actual coordinate system5054 * by:5055 * Bi=[ dh/dx 0 ]5056 * [ 0 dh/dy ]5057 * [ 1/2*dh/dy 1/2*dh/dx ]5058 * [ 1/2*dh/dz 0 ]5059 * [ 0 1/2*dh/dz ]5060 * where h is the interpolation function for grid i.5061 *5062 * We assume B has been allocated already, of size: 5x(NDOF2*numgrids)5063 */5064 5065 int i;5066 const int numgrids=6;5067 const int NDOF3=3;5068 const int NDOF2=2;5069 5070 double dh1dh6[NDOF3][numgrids];5071 5072 /*Get dh1dh6 in actual coordinate system: */5073 GetNodalFunctionsDerivatives(&dh1dh6[0][0],xyz_list, gauss_coord);5074 5075 /*Build B: */5076 for (i=0;i<numgrids;i++){5077 *(B+NDOF2*numgrids*0+NDOF2*i)=dh1dh6[0][i];5078 *(B+NDOF2*numgrids*0+NDOF2*i+1)=0.0;5079 5080 *(B+NDOF2*numgrids*1+NDOF2*i)=0.0;5081 *(B+NDOF2*numgrids*1+NDOF2*i+1)=dh1dh6[1][i];5082 5083 *(B+NDOF2*numgrids*2+NDOF2*i)=(float).5*dh1dh6[1][i];5084 *(B+NDOF2*numgrids*2+NDOF2*i+1)=(float).5*dh1dh6[0][i];5085 5086 *(B+NDOF2*numgrids*3+NDOF2*i)=(float).5*dh1dh6[2][i];5087 *(B+NDOF2*numgrids*3+NDOF2*i+1)=0.0;5088 5089 *(B+NDOF2*numgrids*4+NDOF2*i)=0.0;5090 *(B+NDOF2*numgrids*4+NDOF2*i+1)=(float).5*dh1dh6[2][i];5091 }5092 5093 }5094 /*}}}*/5095 /*FUNCTION Penta::GetB_artdiff {{{1*/5096 void Penta::GetB_artdiff(double* B_artdiff, double* xyz_list, double* gauss_coord){5097 5098 /*Compute B matrix. B=[B1 B2 B3 B4 B5 B6] where Bi is of size 5*DOFPERGRID.5099 * For grid i, Bi' can be expressed in the actual coordinate system5100 * by:5101 * Bi_artdiff=[ dh/dx ]5102 * [ dh/dy ]5103 * where h is the interpolation function for grid i.5104 *5105 * We assume B has been allocated already, of size: 2x(DOFPERGRID*numgrids)5106 */5107 5108 int i;5109 const int calculationdof=3;5110 const int numgrids=6;5111 int DOFPERGRID=1;5112 5113 /*Same thing in the actual coordinate system: */5114 double dh1dh6[calculationdof][numgrids];5115 5116 /*Get dh1dh2dh3 in actual coordinates system : */5117 GetNodalFunctionsDerivatives(&dh1dh6[0][0],xyz_list,gauss_coord);5118 5119 /*Build B': */5120 for (i=0;i<numgrids;i++){5121 *(B_artdiff+DOFPERGRID*numgrids*0+DOFPERGRID*i)=dh1dh6[0][i];5122 *(B_artdiff+DOFPERGRID*numgrids*1+DOFPERGRID*i)=dh1dh6[1][i];5123 }5124 }5125 /*}}}*/5126 /*FUNCTION Penta::GetB_advec {{{1*/5127 void Penta::GetB_advec(double* B_advec, double* xyz_list, double* gauss_coord){5128 5129 /*Compute B matrix. B=[B1 B2 B3 B4 B5 B6] where Bi is of size 5*DOFPERGRID.5130 * For grid i, Bi' can be expressed in the actual coordinate system5131 * by:5132 * Bi_advec =[ h ]5133 * [ h ]5134 * [ h ]5135 * where h is the interpolation function for grid i.5136 *5137 * We assume B has been allocated already, of size: 3x(DOFPERGRID*numgrids)5138 */5139 5140 int i;5141 int calculationdof=3;5142 int numgrids=6;5143 int DOFPERGRID=1;5144 5145 /*Same thing in the actual coordinate system: */5146 double l1l6[6];5147 5148 /*Get dh1dh2dh3 in actual coordinates system : */5149 GetNodalFunctions(l1l6, gauss_coord);5150 5151 /*Build B': */5152 for (i=0;i<numgrids;i++){5153 *(B_advec+DOFPERGRID*numgrids*0+DOFPERGRID*i)=l1l6[i];5154 *(B_advec+DOFPERGRID*numgrids*1+DOFPERGRID*i)=l1l6[i];5155 *(B_advec+DOFPERGRID*numgrids*2+DOFPERGRID*i)=l1l6[i];5156 }5157 }5158 /*}}}*/5159 /*FUNCTION Penta::GetB_conduct {{{1*/5160 void Penta::GetB_conduct(double* B_conduct, double* xyz_list, double* gauss_coord){5161 5162 /*Compute B matrix. B=[B1 B2 B3 B4 B5 B6] where Bi is of size 5*DOFPERGRID.5163 * For grid i, Bi' can be expressed in the actual coordinate system5164 * by:5165 * Bi_conduct=[ dh/dx ]5166 * [ dh/dy ]5167 * [ dh/dz ]5168 * where h is the interpolation function for grid i.5169 *5170 * We assume B has been allocated already, of size: 3x(DOFPERGRID*numgrids)5171 */5172 5173 int i;5174 const int calculationdof=3;5175 const int numgrids=6;5176 int DOFPERGRID=1;5177 5178 /*Same thing in the actual coordinate system: */5179 double dh1dh6[calculationdof][numgrids];5180 5181 /*Get dh1dh2dh3 in actual coordinates system : */5182 GetNodalFunctionsDerivatives(&dh1dh6[0][0],xyz_list,gauss_coord);5183 5184 /*Build B': */5185 for (i=0;i<numgrids;i++){5186 *(B_conduct+DOFPERGRID*numgrids*0+DOFPERGRID*i)=dh1dh6[0][i];5187 *(B_conduct+DOFPERGRID*numgrids*1+DOFPERGRID*i)=dh1dh6[1][i];5188 *(B_conduct+DOFPERGRID*numgrids*2+DOFPERGRID*i)=dh1dh6[2][i];5189 }5190 }5191 /*}}}*/5192 /*FUNCTION Penta::GetB_vert {{{1*/5193 void Penta::GetB_vert(double* B, double* xyz_list, double* gauss_coord){5194 5195 5196 /* Compute B matrix. B=[dh1/dz dh2/dz dh3/dz dh4/dz dh5/dz dh6/dz];5197 where hi is the interpolation function for grid i.*/5198 5199 int i;5200 const int NDOF3=3;5201 const int numgrids=6;5202 double dh1dh6[NDOF3][numgrids];5203 5204 /*Get dh1dh6 in actual coordinate system: */5205 GetNodalFunctionsDerivatives(&dh1dh6[0][0],xyz_list, gauss_coord);5206 5207 /*Build B: */5208 for (i=0;i<numgrids;i++){5209 B[i]=dh1dh6[2][i];5210 }5211 5212 }5213 /*}}}*/5214 /*FUNCTION Penta::GetBPrime {{{1*/5215 void Penta::GetBPrime(double* B, double* xyz_list, double* gauss_coord){5216 5217 /*Compute B prime matrix. B=[B1 B2 B3 B4 B5 B6] where Bi is of size 5*NDOF2.5218 * For grid i, Bi can be expressed in the actual coordinate system5219 * by:5220 * Bi=[ 2*dh/dx dh/dy ]5221 * [ dh/dx 2*dh/dy ]5222 * [ dh/dy dh/dx ]5223 * [ dh/dz 0 ]5224 * [ 0 dh/dz ]5225 * where h is the interpolation function for grid i.5226 *5227 * We assume B has been allocated already, of size: 5x(NDOF2*numgrids)5228 */5229 5230 int i;5231 const int NDOF3=3;5232 const int NDOF2=2;5233 const int numgrids=6;5234 5235 double dh1dh6[NDOF3][numgrids];5236 5237 /*Get dh1dh6 in actual coordinate system: */5238 GetNodalFunctionsDerivatives(&dh1dh6[0][0],xyz_list, gauss_coord);5239 5240 /*Build BPrime: */5241 for (i=0;i<numgrids;i++){5242 *(B+NDOF2*numgrids*0+NDOF2*i)=2.0*dh1dh6[0][i];5243 *(B+NDOF2*numgrids*0+NDOF2*i+1)=dh1dh6[1][i];5244 5245 *(B+NDOF2*numgrids*1+NDOF2*i)=dh1dh6[0][i];5246 *(B+NDOF2*numgrids*1+NDOF2*i+1)=2.0*dh1dh6[1][i];5247 5248 *(B+NDOF2*numgrids*2+NDOF2*i)=dh1dh6[1][i];5249 *(B+NDOF2*numgrids*2+NDOF2*i+1)=dh1dh6[0][i];5250 5251 *(B+NDOF2*numgrids*3+NDOF2*i)=dh1dh6[2][i];5252 *(B+NDOF2*numgrids*3+NDOF2*i+1)=0.0;5253 5254 *(B+NDOF2*numgrids*4+NDOF2*i)=0.0;5255 *(B+NDOF2*numgrids*4+NDOF2*i+1)=dh1dh6[2][i];5256 }5257 }5258 /*}}}*/5259 /*FUNCTION Penta::GetBprime_advec {{{1*/5260 void Penta::GetBprime_advec(double* Bprime_advec, double* xyz_list, double* gauss_coord){5261 5262 5263 /*Compute B matrix. B=[B1 B2 B3 B4 B5 B6] where Bi is of size 5*DOFPERGRID.5264 * For grid i, Bi' can be expressed in the actual coordinate system5265 * by:5266 * Biprime_advec=[ dh/dx ]5267 * [ dh/dy ]5268 * [ dh/dz ]5269 * where h is the interpolation function for grid i.5270 *5271 * We assume B has been allocated already, of size: 3x(DOFPERGRID*numgrids)5272 */5273 5274 int i;5275 const int calculationdof=3;5276 const int numgrids=6;5277 int DOFPERGRID=1;5278 5279 /*Same thing in the actual coordinate system: */5280 double dh1dh6[calculationdof][numgrids];5281 5282 /*Get dh1dh2dh3 in actual coordinates system : */5283 GetNodalFunctionsDerivatives(&dh1dh6[0][0],xyz_list,gauss_coord);5284 5285 /*Build B': */5286 for (i=0;i<numgrids;i++){5287 *(Bprime_advec+DOFPERGRID*numgrids*0+DOFPERGRID*i)=dh1dh6[0][i];5288 *(Bprime_advec+DOFPERGRID*numgrids*1+DOFPERGRID*i)=dh1dh6[1][i];5289 *(Bprime_advec+DOFPERGRID*numgrids*2+DOFPERGRID*i)=dh1dh6[2][i];5290 }5291 }5292 /*}}}*/5293 /*FUNCTION Penta::GetBPrime_vert {{{1*/5294 void Penta::GetBPrime_vert(double* B, double* xyz_list, double* gauss_coord){5295 5296 // Compute Bprime matrix. Bprime=[L1 L2 L3 L4 L5 L6] where Li is the nodal function for grid i5297 5298 int i;5299 5300 GetNodalFunctions(B, gauss_coord);5301 5302 }5303 /*}}}*/5304 /*FUNCTION Penta::GetBprimeStokes {{{1*/5305 void Penta::GetBprimeStokes(double* B_prime, double* xyz_list, double* gauss_coord){5306 5307 /* Compute B' matrix. B'=[B1' B2' B3' B4' B5' B6' Bb'] where Bi' is of size 3*NDOF2.5308 * For grid i, Bi' can be expressed in the actual coordinate system5309 * by:5310 * Bi'=[ dh/dx 0 0 0]5311 * [ 0 dh/dy 0 0]5312 * [ 0 0 dh/dz 0]5313 * [ dh/dy dh/dx 0 0]5314 * [ dh/dz 0 dh/dx 0]5315 * [ 0 dh/dz dh/dy 0]5316 * [ dh/dx dh/dy dh/dz 0]5317 * [ 0 0 0 h]5318 * where h is the interpolation function for grid i.5319 *5320 * Same thing for the bubble fonction except that there is no fourth column5321 */5322 5323 int i;5324 const int calculationdof=3;5325 const int numgrids=6;5326 int DOFPERGRID=4;5327 5328 double dh1dh7[calculationdof][numgrids+1];5329 double l1l6[numgrids];5330 5331 /*Get dh1dh7 in actual coordinate system: */5332 GetNodalFunctionsDerivativesStokes(&dh1dh7[0][0],xyz_list, gauss_coord);5333 5334 GetNodalFunctions(l1l6, gauss_coord);5335 5336 /*B_primeuild B_prime: */5337 for (i=0;i<numgrids+1;i++){5338 *(B_prime+(DOFPERGRID*numgrids+3)*0+DOFPERGRID*i)=dh1dh7[0][i]; //B_prime[0][DOFPERGRID*i]=dh1dh6[0][i];5339 *(B_prime+(DOFPERGRID*numgrids+3)*0+DOFPERGRID*i+1)=0;5340 *(B_prime+(DOFPERGRID*numgrids+3)*0+DOFPERGRID*i+2)=0;5341 *(B_prime+(DOFPERGRID*numgrids+3)*1+DOFPERGRID*i)=0;5342 *(B_prime+(DOFPERGRID*numgrids+3)*1+DOFPERGRID*i+1)=dh1dh7[1][i];5343 *(B_prime+(DOFPERGRID*numgrids+3)*1+DOFPERGRID*i+2)=0;5344 *(B_prime+(DOFPERGRID*numgrids+3)*2+DOFPERGRID*i)=0;5345 *(B_prime+(DOFPERGRID*numgrids+3)*2+DOFPERGRID*i+1)=0;5346 *(B_prime+(DOFPERGRID*numgrids+3)*2+DOFPERGRID*i+2)=dh1dh7[2][i];5347 *(B_prime+(DOFPERGRID*numgrids+3)*3+DOFPERGRID*i)=dh1dh7[1][i];5348 *(B_prime+(DOFPERGRID*numgrids+3)*3+DOFPERGRID*i+1)=dh1dh7[0][i];5349 *(B_prime+(DOFPERGRID*numgrids+3)*3+DOFPERGRID*i+2)=0;5350 *(B_prime+(DOFPERGRID*numgrids+3)*4+DOFPERGRID*i)=dh1dh7[2][i];5351 *(B_prime+(DOFPERGRID*numgrids+3)*4+DOFPERGRID*i+1)=0;5352 *(B_prime+(DOFPERGRID*numgrids+3)*4+DOFPERGRID*i+2)=dh1dh7[0][i];5353 *(B_prime+(DOFPERGRID*numgrids+3)*5+DOFPERGRID*i)=0;5354 *(B_prime+(DOFPERGRID*numgrids+3)*5+DOFPERGRID*i+1)=dh1dh7[2][i];5355 *(B_prime+(DOFPERGRID*numgrids+3)*5+DOFPERGRID*i+2)=dh1dh7[1][i];5356 *(B_prime+(DOFPERGRID*numgrids+3)*6+DOFPERGRID*i)=dh1dh7[0][i];5357 *(B_prime+(DOFPERGRID*numgrids+3)*6+DOFPERGRID*i+1)=dh1dh7[1][i];5358 *(B_prime+(DOFPERGRID*numgrids+3)*6+DOFPERGRID*i+2)=dh1dh7[2][i];5359 *(B_prime+(DOFPERGRID*numgrids+3)*7+DOFPERGRID*i)=0;5360 *(B_prime+(DOFPERGRID*numgrids+3)*7+DOFPERGRID*i+1)=0;5361 *(B_prime+(DOFPERGRID*numgrids+3)*7+DOFPERGRID*i+2)=0;5362 }5363 5364 for (i=0;i<numgrids;i++){ //last column not for the bubble function5365 *(B_prime+(DOFPERGRID*numgrids+3)*0+DOFPERGRID*i+3)=0;5366 *(B_prime+(DOFPERGRID*numgrids+3)*1+DOFPERGRID*i+3)=0;5367 *(B_prime+(DOFPERGRID*numgrids+3)*2+DOFPERGRID*i+3)=0;5368 *(B_prime+(DOFPERGRID*numgrids+3)*3+DOFPERGRID*i+3)=0;5369 *(B_prime+(DOFPERGRID*numgrids+3)*4+DOFPERGRID*i+3)=0;5370 *(B_prime+(DOFPERGRID*numgrids+3)*5+DOFPERGRID*i+3)=0;5371 *(B_prime+(DOFPERGRID*numgrids+3)*6+DOFPERGRID*i+3)=0;5372 *(B_prime+(DOFPERGRID*numgrids+3)*7+DOFPERGRID*i+3)=l1l6[i];5373 }5374 5375 }5376 /*}}}*/5377 /*FUNCTION Penta::GetBStokes {{{1*/5378 void Penta::GetBStokes(double* B, double* xyz_list, double* gauss_coord){5379 5380 /*Compute B matrix. B=[B1 B2 B3 B4 B5 B6] where Bi is of size 3*DOFPERGRID.5381 * For grid i, Bi can be expressed in the actual coordinate system5382 * by: Bi=[ dh/dx 0 0 0 ]5383 * [ 0 dh/dy 0 0 ]5384 * [ 0 0 dh/dy 0 ]5385 * [ 1/2*dh/dy 1/2*dh/dx 0 0 ]5386 * [ 1/2*dh/dz 0 1/2*dh/dx 0 ]5387 * [ 0 1/2*dh/dz 1/2*dh/dy 0 ]5388 * [ 0 0 0 h ]5389 * [ dh/dx dh/dy dh/dz 0 ]5390 * where h is the interpolation function for grid i.5391 * Same thing for Bb except the last column that does not exist.5392 */5393 5394 int i;5395 const int calculationdof=3;5396 const int numgrids=6;5397 int DOFPERGRID=4;5398 5399 double dh1dh7[calculationdof][numgrids+1];5400 double l1l6[numgrids];5401 5402 5403 /*Get dh1dh7 in actual coordinate system: */5404 GetNodalFunctionsDerivativesStokes(&dh1dh7[0][0],xyz_list, gauss_coord);5405 5406 GetNodalFunctions(l1l6, gauss_coord);5407 5408 /*Build B: */5409 for (i=0;i<numgrids+1;i++){5410 *(B+(DOFPERGRID*numgrids+3)*0+DOFPERGRID*i)=dh1dh7[0][i]; //B[0][DOFPERGRID*i]=dh1dh6[0][i];5411 *(B+(DOFPERGRID*numgrids+3)*0+DOFPERGRID*i+1)=0;5412 *(B+(DOFPERGRID*numgrids+3)*0+DOFPERGRID*i+2)=0;5413 *(B+(DOFPERGRID*numgrids+3)*1+DOFPERGRID*i)=0;5414 *(B+(DOFPERGRID*numgrids+3)*1+DOFPERGRID*i+1)=dh1dh7[1][i];5415 *(B+(DOFPERGRID*numgrids+3)*1+DOFPERGRID*i+2)=0;5416 *(B+(DOFPERGRID*numgrids+3)*2+DOFPERGRID*i)=0;5417 *(B+(DOFPERGRID*numgrids+3)*2+DOFPERGRID*i+1)=0;5418 *(B+(DOFPERGRID*numgrids+3)*2+DOFPERGRID*i+2)=dh1dh7[2][i];5419 *(B+(DOFPERGRID*numgrids+3)*3+DOFPERGRID*i)=(float).5*dh1dh7[1][i];5420 *(B+(DOFPERGRID*numgrids+3)*3+DOFPERGRID*i+1)=(float).5*dh1dh7[0][i];5421 *(B+(DOFPERGRID*numgrids+3)*3+DOFPERGRID*i+2)=0;5422 *(B+(DOFPERGRID*numgrids+3)*4+DOFPERGRID*i)=(float).5*dh1dh7[2][i];5423 *(B+(DOFPERGRID*numgrids+3)*4+DOFPERGRID*i+1)=0;5424 *(B+(DOFPERGRID*numgrids+3)*4+DOFPERGRID*i+2)=(float).5*dh1dh7[0][i];5425 *(B+(DOFPERGRID*numgrids+3)*5+DOFPERGRID*i)=0;5426 *(B+(DOFPERGRID*numgrids+3)*5+DOFPERGRID*i+1)=(float).5*dh1dh7[2][i];5427 *(B+(DOFPERGRID*numgrids+3)*5+DOFPERGRID*i+2)=(float).5*dh1dh7[1][i];5428 *(B+(DOFPERGRID*numgrids+3)*6+DOFPERGRID*i)=0;5429 *(B+(DOFPERGRID*numgrids+3)*6+DOFPERGRID*i+1)=0;5430 *(B+(DOFPERGRID*numgrids+3)*6+DOFPERGRID*i+2)=0;5431 *(B+(DOFPERGRID*numgrids+3)*7+DOFPERGRID*i)=dh1dh7[0][i];5432 *(B+(DOFPERGRID*numgrids+3)*7+DOFPERGRID*i+1)=dh1dh7[1][i];5433 *(B+(DOFPERGRID*numgrids+3)*7+DOFPERGRID*i+2)=dh1dh7[2][i];5434 }5435 5436 for (i=0;i<numgrids;i++){ //last column not for the bubble function5437 *(B+(DOFPERGRID*numgrids+3)*0+DOFPERGRID*i+3)=0;5438 *(B+(DOFPERGRID*numgrids+3)*1+DOFPERGRID*i+3)=0;5439 *(B+(DOFPERGRID*numgrids+3)*2+DOFPERGRID*i+3)=0;5440 *(B+(DOFPERGRID*numgrids+3)*3+DOFPERGRID*i+3)=0;5441 *(B+(DOFPERGRID*numgrids+3)*4+DOFPERGRID*i+3)=0;5442 *(B+(DOFPERGRID*numgrids+3)*5+DOFPERGRID*i+3)=0;5443 *(B+(DOFPERGRID*numgrids+3)*6+DOFPERGRID*i+3)=l1l6[i];5444 *(B+(DOFPERGRID*numgrids+3)*7+DOFPERGRID*i+3)=0;5445 }5446 5447 }5448 /*}}}*/5449 /*FUNCTION Penta::GetDofList {{{1*/5450 void Penta::GetDofList(int* doflist,int* pnumberofdofspernode){5451 5452 int i,j;5453 int doflist_per_node[MAXDOFSPERNODE];5454 int numberofdofspernode;5455 5456 for(i=0;i<6;i++){5457 nodes[i]->GetDofList(&doflist_per_node[0],&numberofdofspernode);5458 for(j=0;j<numberofdofspernode;j++){5459 doflist[i*numberofdofspernode+j]=doflist_per_node[j];5460 }5461 }5462 5463 /*Assign output pointers:*/5464 *pnumberofdofspernode=numberofdofspernode;5465 5466 }5467 /*}}}*/5468 /*FUNCTION Penta::GetDofList1 {{{1*/5469 void Penta::GetDofList1(int* doflist){5470 5471 int i;5472 5473 for(i=0;i<6;i++){5474 doflist[i]=nodes[i]->GetDofList1();5475 }5476 5477 }5478 /*}}}*/5479 /*FUNCTION Penta::GetJacobian {{{1*/5480 void Penta::GetJacobian(double* J, double* xyz_list,double* gauss_coord){5481 5482 const int NDOF3=3;5483 int i,j;5484 5485 /*The Jacobian is constant over the element, discard the gaussian points.5486 * J is assumed to have been allocated of size NDOF2xNDOF2.*/5487 5488 double A1,A2,A3; //area coordinates5489 double xi,eta,zi; //parametric coordinates5490 5491 double x1,x2,x3,x4,x5,x6;5492 double y1,y2,y3,y4,y5,y6;5493 double z1,z2,z3,z4,z5,z6;5494 5495 /*Figure out xi,eta and zi (parametric coordinates), for this gaussian point: */5496 A1=gauss_coord[0];5497 A2=gauss_coord[1];5498 A3=gauss_coord[2];5499 5500 xi=A2-A1;5501 eta=SQRT3*A3;5502 zi=gauss_coord[3];5503 5504 x1=*(xyz_list+3*0+0);5505 x2=*(xyz_list+3*1+0);5506 x3=*(xyz_list+3*2+0);5507 x4=*(xyz_list+3*3+0);5508 x5=*(xyz_list+3*4+0);5509 x6=*(xyz_list+3*5+0);5510 5511 y1=*(xyz_list+3*0+1);5512 y2=*(xyz_list+3*1+1);5513 y3=*(xyz_list+3*2+1);5514 y4=*(xyz_list+3*3+1);5515 y5=*(xyz_list+3*4+1);5516 y6=*(xyz_list+3*5+1);5517 5518 z1=*(xyz_list+3*0+2);5519 z2=*(xyz_list+3*1+2);5520 z3=*(xyz_list+3*2+2);5521 z4=*(xyz_list+3*3+2);5522 z5=*(xyz_list+3*4+2);5523 z6=*(xyz_list+3*5+2);5524 5525 5526 *(J+NDOF3*0+0)=0.25*(x1-x2-x4+x5)*zi+0.25*(-x1+x2-x4+x5);5527 *(J+NDOF3*1+0)=SQRT3/12.0*(x1+x2-2*x3-x4-x5+2*x6)*zi+SQRT3/12.0*(-x1-x2+2*x3-x4-x5+2*x6);5528 *(J+NDOF3*2+0)=SQRT3/12.0*(x1+x2-2*x3-x4-x5+2*x6)*eta+1/4*(x1-x2-x4+x5)*xi +0.25*(-x1+x5-x2+x4);5529 5530 *(J+NDOF3*0+1)=0.25*(y1-y2-y4+y5)*zi+0.25*(-y1+y2-y4+y5);5531 *(J+NDOF3*1+1)=SQRT3/12.0*(y1+y2-2*y3-y4-y5+2*y6)*zi+SQRT3/12.0*(-y1-y2+2*y3-y4-y5+2*y6);5532 *(J+NDOF3*2+1)=SQRT3/12.0*(y1+y2-2*y3-y4-y5+2*y6)*eta+0.25*(y1-y2-y4+y5)*xi+0.25*(y4-y1+y5-y2);5533 5534 *(J+NDOF3*0+2)=0.25*(z1-z2-z4+z5)*zi+0.25*(-z1+z2-z4+z5);5535 *(J+NDOF3*1+2)=SQRT3/12.0*(z1+z2-2*z3-z4-z5+2*z6)*zi+SQRT3/12.0*(-z1-z2+2*z3-z4-z5+2*z6);5536 *(J+NDOF3*2+2)=SQRT3/12.0*(z1+z2-2*z3-z4-z5+2*z6)*eta+0.25*(z1-z2-z4+z5)*xi+0.25*(-z1+z5-z2+z4);5537 5538 }5539 /*}}}*/5540 /*FUNCTION Penta::GetJacobianDeterminant {{{1*/5541 void Penta::GetJacobianDeterminant(double* Jdet, double* xyz_list,double* gauss_coord){5542 5543 /*On a penta, Jacobian varies according to coordinates. We need to get the Jacobian, and take5544 * the determinant of it: */5545 const int NDOF3=3;5546 5547 double J[NDOF3][NDOF3];5548 5549 GetJacobian(&J[0][0],xyz_list,gauss_coord);5550 5551 *Jdet= J[0][0]*J[1][1]*J[2][2]-J[0][0]*J[1][2]*J[2][1]-J[1][0]*J[0][1]*J[2][2]+J[1][0]*J[0][2]*J[2][1]+J[2][0]*J[0][1]*J[1][2]-J[2][0]*J[0][2]*J[1][1];5552 5553 if(*Jdet<0){5554 ISSMERROR("%s%i","negative jacobian determinant on element ",id);5555 }5556 }5557 /*}}}*/5558 /*FUNCTION Penta::GetJacobianInvert {{{1*/5559 void Penta::GetJacobianInvert(double* Jinv, double* xyz_list,double* gauss_coord){5560 5561 double Jdet;5562 const int NDOF3=3;5563 5564 /*Call Jacobian routine to get the jacobian:*/5565 GetJacobian(Jinv, xyz_list, gauss_coord);5566 5567 /*Invert Jacobian matrix: */5568 MatrixInverse(Jinv,NDOF3,NDOF3,NULL,0,&Jdet);5569 }5570 /*}}}*/5571 /*FUNCTION Penta::GetLStokes {{{1*/5572 void Penta::GetLStokes(double* LStokes, double* gauss_coord_tria){5573 5574 /*5575 * Compute L matrix. L=[L1 L2 L3] where Li is square and of size numdof.5576 * For grid i, Li can be expressed in the actual coordinate system5577 * by:5578 * Li=[ h 0 0 0]5579 * [ 0 h 0 0]5580 * [ 0 0 h 0]5581 * [ 0 0 h 0]5582 * [ h 0 0 0]5583 * [ 0 h 0 0]5584 * [ h 0 0 0]5585 * [ 0 h 0 0]5586 * [ 0 0 h 0]5587 * [ 0 0 h 0]5588 * [ 0 0 h 0]5589 * [ h 0 0 0]5590 * [ 0 h 0 0]5591 * [ 0 0 h 0]5592 * where h is the interpolation function for grid i.5593 */5594 5595 int i;5596 const int numgrids2d=3;5597 int num_dof=4;5598 5599 double l1l2l3[numgrids2d];5600 5601 5602 /*Get l1l2l3 in actual coordinate system: */5603 l1l2l3[0]=gauss_coord_tria[0];5604 l1l2l3[1]=gauss_coord_tria[1];5605 l1l2l3[2]=gauss_coord_tria[2];5606 5607 /*Build LStokes: */5608 for (i=0;i<3;i++){5609 *(LStokes+num_dof*numgrids2d*0+num_dof*i)=l1l2l3[i]; //LStokes[0][NDOF2*i]=dh1dh3[0][i];5610 *(LStokes+num_dof*numgrids2d*0+num_dof*i+1)=0;5611 *(LStokes+num_dof*numgrids2d*0+num_dof*i+2)=0;5612 *(LStokes+num_dof*numgrids2d*0+num_dof*i+3)=0;5613 *(LStokes+num_dof*numgrids2d*1+num_dof*i)=0;5614 *(LStokes+num_dof*numgrids2d*1+num_dof*i+1)=l1l2l3[i];5615 *(LStokes+num_dof*numgrids2d*1+num_dof*i+2)=0;5616 *(LStokes+num_dof*numgrids2d*1+num_dof*i+3)=0;5617 *(LStokes+num_dof*numgrids2d*2+num_dof*i)=0;5618 *(LStokes+num_dof*numgrids2d*2+num_dof*i+1)=0;5619 *(LStokes+num_dof*numgrids2d*2+num_dof*i+2)=l1l2l3[i];5620 *(LStokes+num_dof*numgrids2d*2+num_dof*i+3)=0;5621 *(LStokes+num_dof*numgrids2d*3+num_dof*i)=0;5622 *(LStokes+num_dof*numgrids2d*3+num_dof*i+1)=0;5623 *(LStokes+num_dof*numgrids2d*3+num_dof*i+2)=l1l2l3[i];5624 *(LStokes+num_dof*numgrids2d*3+num_dof*i+3)=0;5625 *(LStokes+num_dof*numgrids2d*4+num_dof*i)=l1l2l3[i];5626 *(LStokes+num_dof*numgrids2d*4+num_dof*i+1)=0;5627 *(LStokes+num_dof*numgrids2d*4+num_dof*i+2)=0;5628 *(LStokes+num_dof*numgrids2d*4+num_dof*i+3)=0;5629 *(LStokes+num_dof*numgrids2d*5+num_dof*i)=0;5630 *(LStokes+num_dof*numgrids2d*5+num_dof*i+1)=l1l2l3[i];5631 *(LStokes+num_dof*numgrids2d*5+num_dof*i+2)=0;5632 *(LStokes+num_dof*numgrids2d*5+num_dof*i+3)=0;5633 *(LStokes+num_dof*numgrids2d*6+num_dof*i)=l1l2l3[i];5634 *(LStokes+num_dof*numgrids2d*6+num_dof*i+1)=0;5635 *(LStokes+num_dof*numgrids2d*6+num_dof*i+2)=0;5636 *(LStokes+num_dof*numgrids2d*6+num_dof*i+3)=0;5637 *(LStokes+num_dof*numgrids2d*7+num_dof*i)=0;5638 *(LStokes+num_dof*numgrids2d*7+num_dof*i+1)=l1l2l3[i];5639 *(LStokes+num_dof*numgrids2d*7+num_dof*i+2)=0;5640 *(LStokes+num_dof*numgrids2d*7+num_dof*i+3)=0;5641 *(LStokes+num_dof*numgrids2d*8+num_dof*i)=0;5642 *(LStokes+num_dof*numgrids2d*8+num_dof*i+1)=0;5643 *(LStokes+num_dof*numgrids2d*8+num_dof*i+2)=l1l2l3[i];5644 *(LStokes+num_dof*numgrids2d*8+num_dof*i+3)=0;5645 *(LStokes+num_dof*numgrids2d*9+num_dof*i)=0;5646 *(LStokes+num_dof*numgrids2d*9+num_dof*i+1)=0;5647 *(LStokes+num_dof*numgrids2d*9+num_dof*i+2)=l1l2l3[i];5648 *(LStokes+num_dof*numgrids2d*9+num_dof*i+3)=0;5649 *(LStokes+num_dof*numgrids2d*10+num_dof*i)=0;5650 *(LStokes+num_dof*numgrids2d*10+num_dof*i+1)=0;5651 *(LStokes+num_dof*numgrids2d*10+num_dof*i+2)=l1l2l3[i];5652 *(LStokes+num_dof*numgrids2d*10+num_dof*i+3)=0;5653 *(LStokes+num_dof*numgrids2d*11+num_dof*i)=l1l2l3[i];5654 *(LStokes+num_dof*numgrids2d*11+num_dof*i+1)=0;5655 *(LStokes+num_dof*numgrids2d*11+num_dof*i+2)=0;5656 *(LStokes+num_dof*numgrids2d*11+num_dof*i+3)=0;5657 *(LStokes+num_dof*numgrids2d*12+num_dof*i)=0;5658 *(LStokes+num_dof*numgrids2d*12+num_dof*i+1)=l1l2l3[i];5659 *(LStokes+num_dof*numgrids2d*12+num_dof*i+2)=0;5660 *(LStokes+num_dof*numgrids2d*12+num_dof*i+3)=0;5661 *(LStokes+num_dof*numgrids2d*13+num_dof*i)=0;5662 *(LStokes+num_dof*numgrids2d*13+num_dof*i+1)=0;5663 *(LStokes+num_dof*numgrids2d*13+num_dof*i+2)=l1l2l3[i];5664 *(LStokes+num_dof*numgrids2d*13+num_dof*i+3)=0;5665 5666 }5667 }5668 /*}}}*/5669 /*FUNCTION Penta::GetLprimeStokes {{{1*/5670 void Penta::GetLprimeStokes(double* LprimeStokes, double* xyz_list, double* gauss_coord_tria, double* gauss_coord){5671 5672 /*5673 * Compute Lprime matrix. Lprime=[Lp1 Lp2 Lp3] where Lpi is square and of size numdof.5674 * For grid i, Lpi can be expressed in the actual coordinate system5675 * by:5676 * Lpi=[ h 0 0 0]5677 * [ 0 h 0 0]5678 * [ h 0 0 0]5679 * [ 0 h 0 0]5680 * [ 0 0 h 0]5681 * [ 0 0 h 0]5682 * [ 0 0 dh/dz 0]5683 * [ 0 0 dh/dz 0]5684 * [ 0 0 dh/dz 0]5685 * [dh/dz 0 dh/dx 0]5686 * [ 0 dh/dz dh/dy 0]5687 * [ 0 0 0 h]5688 * [ 0 0 0 h]5689 * [ 0 0 0 h]5690 * where h is the interpolation function for grid i.5691 */5692 5693 int i;5694 const int numgrids2d=3;5695 int num_dof=4;5696 5697 double l1l2l3[numgrids2d];5698 double dh1dh6[3][6];5699 5700 5701 /*Get l1l2l3 in actual coordinate system: */5702 l1l2l3[0]=gauss_coord_tria[0];5703 l1l2l3[1]=gauss_coord_tria[1];5704 l1l2l3[2]=gauss_coord_tria[2];5705 5706 GetNodalFunctionsDerivatives(&dh1dh6[0][0],xyz_list,gauss_coord);5707 5708 /*Build LprimeStokes: */5709 for (i=0;i<3;i++){5710 *(LprimeStokes+num_dof*numgrids2d*0+num_dof*i)=l1l2l3[i]; //LprimeStokes[0][NDOF2*i]=dh1dh3[0][i];5711 *(LprimeStokes+num_dof*numgrids2d*0+num_dof*i+1)=0;5712 *(LprimeStokes+num_dof*numgrids2d*0+num_dof*i+2)=0;5713 *(LprimeStokes+num_dof*numgrids2d*0+num_dof*i+3)=0;5714 *(LprimeStokes+num_dof*numgrids2d*1+num_dof*i)=0;5715 *(LprimeStokes+num_dof*numgrids2d*1+num_dof*i+1)=l1l2l3[i];5716 *(LprimeStokes+num_dof*numgrids2d*1+num_dof*i+2)=0;5717 *(LprimeStokes+num_dof*numgrids2d*1+num_dof*i+3)=0;5718 *(LprimeStokes+num_dof*numgrids2d*2+num_dof*i)=l1l2l3[i];5719 *(LprimeStokes+num_dof*numgrids2d*2+num_dof*i+1)=0;5720 *(LprimeStokes+num_dof*numgrids2d*2+num_dof*i+2)=0;5721 *(LprimeStokes+num_dof*numgrids2d*2+num_dof*i+3)=0;5722 *(LprimeStokes+num_dof*numgrids2d*3+num_dof*i)=0;5723 *(LprimeStokes+num_dof*numgrids2d*3+num_dof*i+1)=l1l2l3[i];5724 *(LprimeStokes+num_dof*numgrids2d*3+num_dof*i+2)=0;5725 *(LprimeStokes+num_dof*numgrids2d*3+num_dof*i+3)=0;5726 *(LprimeStokes+num_dof*numgrids2d*4+num_dof*i)=0;5727 *(LprimeStokes+num_dof*numgrids2d*4+num_dof*i+1)=0;5728 *(LprimeStokes+num_dof*numgrids2d*4+num_dof*i+2)=l1l2l3[i];5729 *(LprimeStokes+num_dof*numgrids2d*4+num_dof*i+3)=0;5730 *(LprimeStokes+num_dof*numgrids2d*5+num_dof*i)=0;5731 *(LprimeStokes+num_dof*numgrids2d*5+num_dof*i+1)=0;5732 *(LprimeStokes+num_dof*numgrids2d*5+num_dof*i+2)=l1l2l3[i];5733 *(LprimeStokes+num_dof*numgrids2d*5+num_dof*i+3)=0;5734 *(LprimeStokes+num_dof*numgrids2d*6+num_dof*i)=0;5735 *(LprimeStokes+num_dof*numgrids2d*6+num_dof*i+1)=0;5736 *(LprimeStokes+num_dof*numgrids2d*6+num_dof*i+2)=dh1dh6[2][i];5737 *(LprimeStokes+num_dof*numgrids2d*6+num_dof*i+3)=0;5738 *(LprimeStokes+num_dof*numgrids2d*7+num_dof*i)=0;5739 *(LprimeStokes+num_dof*numgrids2d*7+num_dof*i+1)=0;5740 *(LprimeStokes+num_dof*numgrids2d*7+num_dof*i+2)=dh1dh6[2][i];5741 *(LprimeStokes+num_dof*numgrids2d*7+num_dof*i+3)=0;5742 *(LprimeStokes+num_dof*numgrids2d*8+num_dof*i)=0;5743 *(LprimeStokes+num_dof*numgrids2d*8+num_dof*i+1)=0;5744 *(LprimeStokes+num_dof*numgrids2d*8+num_dof*i+2)=dh1dh6[2][i];5745 *(LprimeStokes+num_dof*numgrids2d*8+num_dof*i+3)=0;5746 *(LprimeStokes+num_dof*numgrids2d*9+num_dof*i)=dh1dh6[2][i];5747 *(LprimeStokes+num_dof*numgrids2d*9+num_dof*i+1)=0;5748 *(LprimeStokes+num_dof*numgrids2d*9+num_dof*i+2)=dh1dh6[0][i];5749 *(LprimeStokes+num_dof*numgrids2d*9+num_dof*i+3)=0;5750 *(LprimeStokes+num_dof*numgrids2d*10+num_dof*i)=0;5751 *(LprimeStokes+num_dof*numgrids2d*10+num_dof*i+1)=dh1dh6[2][i];5752 *(LprimeStokes+num_dof*numgrids2d*10+num_dof*i+2)=dh1dh6[1][i];5753 *(LprimeStokes+num_dof*numgrids2d*10+num_dof*i+3)=0;5754 *(LprimeStokes+num_dof*numgrids2d*11+num_dof*i)=0;5755 *(LprimeStokes+num_dof*numgrids2d*11+num_dof*i+1)=0;5756 *(LprimeStokes+num_dof*numgrids2d*11+num_dof*i+2)=0;5757 *(LprimeStokes+num_dof*numgrids2d*11+num_dof*i+3)=l1l2l3[i];5758 *(LprimeStokes+num_dof*numgrids2d*12+num_dof*i)=0;5759 *(LprimeStokes+num_dof*numgrids2d*12+num_dof*i+1)=0;5760 *(LprimeStokes+num_dof*numgrids2d*12+num_dof*i+2)=0;5761 *(LprimeStokes+num_dof*numgrids2d*12+num_dof*i+3)=l1l2l3[i];5762 *(LprimeStokes+num_dof*numgrids2d*13+num_dof*i)=0;5763 *(LprimeStokes+num_dof*numgrids2d*13+num_dof*i+1)=0;5764 *(LprimeStokes+num_dof*numgrids2d*13+num_dof*i+2)=0;5765 *(LprimeStokes+num_dof*numgrids2d*13+num_dof*i+3)=l1l2l3[i];5766 5767 }5768 }5769 /*}}}*/5770 /*FUNCTION Penta::GetMatrixInvert {{{1*/5771 void Penta::GetMatrixInvert(double* Ke_invert, double* Ke){5772 /*Inverse a 3 by 3 matrix only */5773 5774 double a,b,c,d,e,f,g,h,i;5775 double det;5776 int calculationdof=3;5777 5778 /*Take the matrix components: */5779 a=*(Ke+calculationdof*0+0);5780 b=*(Ke+calculationdof*0+1);5781 c=*(Ke+calculationdof*0+2);5782 d=*(Ke+calculationdof*1+0);5783 e=*(Ke+calculationdof*1+1);5784 f=*(Ke+calculationdof*1+2);5785 g=*(Ke+calculationdof*2+0);5786 h=*(Ke+calculationdof*2+1);5787 i=*(Ke+calculationdof*2+2);5788 5789 det=a*(e*i-f*h)-b*(d*i-f*g)+c*(d*h-e*g);5790 5791 *(Ke_invert+calculationdof*0+0)=(e*i-f*h)/det;5792 *(Ke_invert+calculationdof*0+1)=(c*h-b*i)/det;5793 *(Ke_invert+calculationdof*0+2)=(b*f-c*e)/det;5794 *(Ke_invert+calculationdof*1+0)=(f*g-d*i)/det;5795 *(Ke_invert+calculationdof*1+1)=(a*i-c*g)/det;5796 *(Ke_invert+calculationdof*1+2)=(c*d-a*f)/det;5797 *(Ke_invert+calculationdof*2+0)=(d*h-e*g)/det;5798 *(Ke_invert+calculationdof*2+1)=(b*g-a*h)/det;5799 *(Ke_invert+calculationdof*2+2)=(a*e-b*d)/det;5800 5801 }5802 /*}}}*/5803 /*FUNCTION Penta::GetNodalFunctions {{{1*/5804 void Penta::GetNodalFunctions(double* l1l6, double* gauss_coord){5805 5806 /*This routine returns the values of the nodal functions at the gaussian point.*/5807 5808 l1l6[0]=gauss_coord[0]*(1-gauss_coord[3])/2.0;5809 5810 l1l6[1]=gauss_coord[1]*(1-gauss_coord[3])/2.0;5811 5812 l1l6[2]=gauss_coord[2]*(1-gauss_coord[3])/2.0;5813 5814 l1l6[3]=gauss_coord[0]*(1+gauss_coord[3])/2.0;5815 5816 l1l6[4]=gauss_coord[1]*(1+gauss_coord[3])/2.0;5817 5818 l1l6[5]=gauss_coord[2]*(1+gauss_coord[3])/2.0;5819 5820 }5821 /*}}}*/5822 /*FUNCTION Penta::GetNodalFunctionsDerivatives {{{1*/5823 void Penta::GetNodalFunctionsDerivatives(double* dh1dh6,double* xyz_list, double* gauss_coord){5824 5825 /*This routine returns the values of the nodal functions derivatives (with respect to the actual coordinate system: */5826 5827 5828 int i;5829 const int NDOF3=3;5830 const int numgrids=6;5831 5832 double dh1dh6_ref[NDOF3][numgrids];5833 double Jinv[NDOF3][NDOF3];5834 5835 /*Get derivative values with respect to parametric coordinate system: */5836 GetNodalFunctionsDerivativesReference(&dh1dh6_ref[0][0], gauss_coord);5837 5838 /*Get Jacobian invert: */5839 GetJacobianInvert(&Jinv[0][0], xyz_list, gauss_coord);5840 5841 /*Build dh1dh3:5842 *5843 * [dhi/dx]= Jinv*[dhi/dr]5844 * [dhi/dy] [dhi/ds]5845 * [dhi/dz] [dhi/dn]5846 */5847 5848 for (i=0;i<numgrids;i++){5849 *(dh1dh6+numgrids*0+i)=Jinv[0][0]*dh1dh6_ref[0][i]+Jinv[0][1]*dh1dh6_ref[1][i]+Jinv[0][2]*dh1dh6_ref[2][i];5850 *(dh1dh6+numgrids*1+i)=Jinv[1][0]*dh1dh6_ref[0][i]+Jinv[1][1]*dh1dh6_ref[1][i]+Jinv[1][2]*dh1dh6_ref[2][i];5851 *(dh1dh6+numgrids*2+i)=Jinv[2][0]*dh1dh6_ref[0][i]+Jinv[2][1]*dh1dh6_ref[1][i]+Jinv[2][2]*dh1dh6_ref[2][i];5852 }5853 5854 }5855 /*}}}*/5856 /*FUNCTION Penta::GetNodalFunctionsDerivativesStokes {{{1*/5857 void Penta::GetNodalFunctionsDerivativesStokes(double* dh1dh7,double* xyz_list, double* gauss_coord){5858 5859 /*This routine returns the values of the nodal functions derivatives (with respect to the5860 * actual coordinate system: */5861 5862 int i;5863 5864 const int numgrids=7;5865 double dh1dh7_ref[3][numgrids];5866 double Jinv[3][3];5867 5868 5869 /*Get derivative values with respect to parametric coordinate system: */5870 GetNodalFunctionsDerivativesReferenceStokes(&dh1dh7_ref[0][0], gauss_coord);5871 5872 /*Get Jacobian invert: */5873 GetJacobianInvert(&Jinv[0][0], xyz_list, gauss_coord);5874 5875 /*Build dh1dh6:5876 *5877 * [dhi/dx]= Jinv'*[dhi/dr]5878 * [dhi/dy] [dhi/ds]5879 * [dhi/dz] [dhi/dzeta]5880 */5881 5882 for (i=0;i<numgrids;i++){5883 *(dh1dh7+numgrids*0+i)=Jinv[0][0]*dh1dh7_ref[0][i]+Jinv[0][1]*dh1dh7_ref[1][i]+Jinv[0][2]*dh1dh7_ref[2][i];5884 *(dh1dh7+numgrids*1+i)=Jinv[1][0]*dh1dh7_ref[0][i]+Jinv[1][1]*dh1dh7_ref[1][i]+Jinv[1][2]*dh1dh7_ref[2][i];5885 *(dh1dh7+numgrids*2+i)=Jinv[2][0]*dh1dh7_ref[0][i]+Jinv[2][1]*dh1dh7_ref[1][i]+Jinv[2][2]*dh1dh7_ref[2][i];5886 }5887 5888 }5889 /*}}}*/5890 /*FUNCTION Penta::GetNodalFunctionsDerivativesReference {{{1*/5891 void Penta::GetNodalFunctionsDerivativesReference(double* dl1dl6,double* gauss_coord){5892 5893 /*This routine returns the values of the nodal functions derivatives (with respect to the5894 * natural coordinate system) at the gaussian point. Those values vary along xi,eta,z */5895 5896 const int numgrids=6;5897 double A1,A2,A3,z;5898 5899 A1=gauss_coord[0]; //first area coordinate value. In term of xi and eta: A1=(1-xi)/2-eta/(2*SQRT3);5900 A2=gauss_coord[1]; //second area coordinate value In term of xi and eta: A2=(1+xi)/2-eta/(2*SQRT3);5901 A3=gauss_coord[2]; //third area coordinate value In term of xi and eta: A3=y/SQRT3;5902 z=gauss_coord[3]; //fourth vertical coordinate value. Corresponding nodal function: (1-z)/2 and (1+z)/25903 5904 5905 /*First nodal function derivatives. The corresponding nodal function is N=A1*(1-z)/2. Its derivatives follow*/5906 *(dl1dl6+numgrids*0+0)=-0.5*(1.0-z)/2.0;5907 *(dl1dl6+numgrids*1+0)=-0.5/SQRT3*(1.0-z)/2.0;5908 *(dl1dl6+numgrids*2+0)=-0.5*A1;5909 5910 /*Second nodal function: The corresponding nodal function is N=A2*(1-z)/2. Its derivatives follow*/5911 *(dl1dl6+numgrids*0+1)=0.5*(1.0-z)/2.0;5912 *(dl1dl6+numgrids*1+1)=-0.5/SQRT3*(1.0-z)/2.0;5913 *(dl1dl6+numgrids*2+1)=-0.5*A2;5914 5915 /*Third nodal function: The corresponding nodal function is N=A3*(1-z)/2. Its derivatives follow*/5916 *(dl1dl6+numgrids*0+2)=0.0;5917 *(dl1dl6+numgrids*1+2)=1.0/SQRT3*(1.0-z)/2.0;5918 *(dl1dl6+numgrids*2+2)=-0.5*A3;5919 5920 /*Fourth nodal function: The corresponding nodal function is N=A1*(1+z)/2. Its derivatives follow*/5921 *(dl1dl6+numgrids*0+3)=-0.5*(1.0+z)/2.0;5922 *(dl1dl6+numgrids*1+3)=-0.5/SQRT3*(1.0+z)/2.0;5923 *(dl1dl6+numgrids*2+3)=0.5*A1;5924 5925 /*Fifth nodal function: The corresponding nodal function is N=A2*(1+z)/2. Its derivatives follow*/5926 *(dl1dl6+numgrids*0+4)=0.5*(1.0+z)/2.0;5927 *(dl1dl6+numgrids*1+4)=-0.5/SQRT3*(1.0+z)/2.0;5928 *(dl1dl6+numgrids*2+4)=0.5*A2;5929 5930 /*Sixth nodal function: The corresponding nodal function is N=A3*(1+z)/2. Its derivatives follow*/5931 *(dl1dl6+numgrids*0+5)=0.0;5932 *(dl1dl6+numgrids*1+5)=1.0/SQRT3*(1.0+z)/2.0;5933 *(dl1dl6+numgrids*2+5)=0.5*A3;5934 }5935 /*}}}*/5936 /*FUNCTION Penta::GetNodalFunctionsDerivativesReferenceStokes {{{1*/5937 void Penta::GetNodalFunctionsDerivativesReferenceStokes(double* dl1dl7,double* gauss_coord){5938 5939 /*This routine returns the values of the nodal functions derivatives (with respect to the5940 * natural coordinate system) at the gaussian point. */5941 5942 int numgrids=7; //six plus bubble grids5943 5944 double r=gauss_coord[1]-gauss_coord[0];5945 double s=-3.0/SQRT3*(gauss_coord[0]+gauss_coord[1]-2.0/3.0);5946 double zeta=gauss_coord[3];5947 5948 /*First nodal function: */5949 *(dl1dl7+numgrids*0+0)=-0.5*(1.0-zeta)/2.0;5950 *(dl1dl7+numgrids*1+0)=-SQRT3/6.0*(1.0-zeta)/2.0;5951 *(dl1dl7+numgrids*2+0)=-0.5*(-0.5*r-SQRT3/6.0*s+ONETHIRD);5952 5953 /*Second nodal function: */5954 *(dl1dl7+numgrids*0+1)=0.5*(1.0-zeta)/2.0;5955 *(dl1dl7+numgrids*1+1)=-SQRT3/6.0*(1.0-zeta)/2.0;5956 *(dl1dl7+numgrids*2+1)=-0.5*(0.5*r-SQRT3/6.0*s+ONETHIRD);5957 5958 /*Third nodal function: */5959 *(dl1dl7+numgrids*0+2)=0;5960 *(dl1dl7+numgrids*1+2)=SQRT3/3.0*(1.0-zeta)/2.0;5961 *(dl1dl7+numgrids*2+2)=-0.5*(SQRT3/3.0*s+ONETHIRD);5962 5963 /*Fourth nodal function: */5964 *(dl1dl7+numgrids*0+3)=-0.5*(1.0+zeta)/2.0;5965 *(dl1dl7+numgrids*1+3)=-SQRT3/6.0*(1.0+zeta)/2.0;5966 *(dl1dl7+numgrids*2+3)=0.5*(-0.5*r-SQRT3/6.0*s+ONETHIRD);5967 5968 /*Fith nodal function: */5969 *(dl1dl7+numgrids*0+4)=0.5*(1.0+zeta)/2.0;5970 *(dl1dl7+numgrids*1+4)=-SQRT3/6.0*(1.0+zeta)/2.0;5971 *(dl1dl7+numgrids*2+4)=0.5*(0.5*r-SQRT3/6.0*s+ONETHIRD);5972 5973 /*Sixth nodal function: */5974 *(dl1dl7+numgrids*0+5)=0;5975 *(dl1dl7+numgrids*1+5)=SQRT3/3.0*(1.0+zeta)/2.0;5976 *(dl1dl7+numgrids*2+5)=0.5*(SQRT3/3.0*s+ONETHIRD);5977 5978 /*Seventh nodal function: */5979 *(dl1dl7+numgrids*0+6)=9.0/2.0*r*(1.0+zeta)*(zeta-1.0)*(SQRT3*s+1.0);5980 *(dl1dl7+numgrids*1+6)=9.0/4.0*(1+zeta)*(1-zeta)*(SQRT3*pow(s,2.0)-2.0*s-SQRT3*pow(r,2.0));5981 *(dl1dl7+numgrids*2+6)=27*gauss_coord[0]*gauss_coord[1]*gauss_coord[2]*(-2.0*zeta);5982 5983 }5984 /*}}}*/5985 /*FUNCTION Penta::GetNodalFunctionsStokes {{{1*/5986 void Penta::GetNodalFunctionsStokes(double* l1l7, double* gauss_coord){5987 5988 /*This routine returns the values of the nodal functions at the gaussian point.*/5989 5990 /*First nodal function: */5991 l1l7[0]=gauss_coord[0]*(1.0-gauss_coord[3])/2.0;5992 5993 /*Second nodal function: */5994 l1l7[1]=gauss_coord[1]*(1.0-gauss_coord[3])/2.0;5995 5996 /*Third nodal function: */5997 l1l7[2]=gauss_coord[2]*(1.0-gauss_coord[3])/2.0;5998 5999 /*Fourth nodal function: */6000 l1l7[3]=gauss_coord[0]*(1.0+gauss_coord[3])/2.0;6001 6002 /*Fifth nodal function: */6003 l1l7[4]=gauss_coord[1]*(1.0+gauss_coord[3])/2.0;6004 6005 /*Sixth nodal function: */6006 l1l7[5]=gauss_coord[2]*(1.0+gauss_coord[3])/2.0;6007 6008 /*Seventh nodal function: */6009 l1l7[6]=27*gauss_coord[0]*gauss_coord[1]*gauss_coord[2]*(1.0+gauss_coord[3])*(1.0-gauss_coord[3]);6010 6011 }6012 /*}}}*/6013 /*FUNCTION Penta::GetParameterDerivativeValue {{{1*/6014 void Penta::GetParameterDerivativeValue(double* p, double* p_list,double* xyz_list, double* gauss_coord){6015 6016 /*From grid values of parameter p (p_list[0], p_list[1], p_list[2], p_list[3], p_list[4] and p_list[4]), return parameter derivative value at gaussian point specified by gauss_coord:6017 * dp/dx=p_list[0]*dh1/dx+p_list[1]*dh2/dx+p_list[2]*dh3/dx+p_list[3]*dh4/dx+p_list[4]*dh5/dx+p_list[5]*dh6/dx;6018 * dp/dy=p_list[0]*dh1/dy+p_list[1]*dh2/dy+p_list[2]*dh3/dy+p_list[3]*dh4/dy+p_list[4]*dh5/dy+p_list[5]*dh6/dy;6019 * dp/dz=p_list[0]*dh1/dz+p_list[1]*dh2/dz+p_list[2]*dh3/dz+p_list[3]*dh4/dz+p_list[4]*dh5/dz+p_list[5]*dh6/dz;6020 *6021 * p is a vector of size 3x1 already allocated.6022 */6023 6024 const int NDOF3=3;6025 const int numgrids=6;6026 double dh1dh6[NDOF3][numgrids];6027 6028 /*Get dh1dh6 in actual coordinate system: */6029 GetNodalFunctionsDerivatives(&dh1dh6[0][0],xyz_list, gauss_coord);6030 6031 *(p+0)=p_list[0]*dh1dh6[0][0]+p_list[1]*dh1dh6[0][1]+p_list[2]*dh1dh6[0][2]+p_list[3]*dh1dh6[0][3]+p_list[4]*dh1dh6[0][4]+p_list[5]*dh1dh6[0][5];6032 ;6033 *(p+1)=p_list[0]*dh1dh6[1][0]+p_list[1]*dh1dh6[1][1]+p_list[2]*dh1dh6[1][2]+p_list[3]*dh1dh6[1][3]+p_list[4]*dh1dh6[1][4]+p_list[5]*dh1dh6[1][5];6034 6035 *(p+2)=p_list[0]*dh1dh6[2][0]+p_list[1]*dh1dh6[2][1]+p_list[2]*dh1dh6[2][2]+p_list[3]*dh1dh6[2][3]+p_list[4]*dh1dh6[2][4]+p_list[5]*dh1dh6[2][5];6036 6037 }6038 /*}}}*/6039 /*FUNCTION Penta::GetParameterValue(double* pvalue, double* v_list,double* gauss_coord) {{{1*/6040 void Penta::GetParameterValue(double* pvalue, double* v_list,double* gauss_coord){6041 6042 const int numgrids=6;6043 double l1l6[numgrids];6044 6045 GetNodalFunctions(&l1l6[0], gauss_coord);6046 6047 *pvalue=l1l6[0]*v_list[0]+l1l6[1]*v_list[1]+l1l6[2]*v_list[2]+l1l6[3]*v_list[3]+l1l6[4]*v_list[4]+l1l6[5]*v_list[5];6048 }6049 /*}}}*/6050 /*FUNCTION Penta::GetParameterValue(double* pvalue,Node* node1,Node* node2,double gauss_seg,int enumtype) {{{1*/6051 void Penta::GetParameterValue(double* pvalue,Node* node,int enumtype){6052 6053 /*Output*/6054 double value;6055 6056 /*Intermediaries*/6057 const int numnodes=6;6058 int grid=-1;6059 int i;6060 double gauss[numnodes][4]={{1,0,0,-1},{0,1,0,-1},{0,0,1,-1},{1,0,0,1},{0,1,0,1},{0,0,1,1}};6061 6062 /*go through 3 nodes (all nodes for tria) and identify 1st and 2nd nodes: */6063 ISSMASSERT(nodes);6064 for(i=0;i<numnodes;i++){6065 if (node==nodes[i]){6066 grid=i;6067 break;6068 }6069 }6070 6071 /*Check that the node has been found*/6072 if (grid==-1) ISSMERROR("Node pointer not found in Penta's nodes");6073 6074 /*Get Parameter value on node*/6075 inputs->GetParameterValue(pvalue,&gauss[grid][0],enumtype);6076 return;6077 6078 }6079 /*}}}*/6080 /*FUNCTION Penta::GetPhi {{{1*/6081 void Penta::GetPhi(double* phi, double* epsilon, double viscosity){6082 /*Compute deformational heating from epsilon and viscosity */6083 6084 double epsilon_matrix[3][3];6085 double epsilon_eff;6086 double epsilon_sqr[3][3];6087 6088 /* Build epsilon matrix */6089 epsilon_matrix[0][0]=*(epsilon+0);6090 epsilon_matrix[1][0]=*(epsilon+3);6091 epsilon_matrix[2][0]=*(epsilon+4);6092 epsilon_matrix[0][1]=*(epsilon+3);6093 epsilon_matrix[1][1]=*(epsilon+1);6094 epsilon_matrix[2][1]=*(epsilon+5);6095 epsilon_matrix[0][2]=*(epsilon+4);6096 epsilon_matrix[1][2]=*(epsilon+5);6097 epsilon_matrix[2][2]=*(epsilon+2);6098 6099 /* Effective value of epsilon_matrix */6100 epsilon_sqr[0][0]=pow(epsilon_matrix[0][0],2);6101 epsilon_sqr[1][0]=pow(epsilon_matrix[1][0],2);6102 epsilon_sqr[2][0]=pow(epsilon_matrix[2][0],2);6103 epsilon_sqr[0][1]=pow(epsilon_matrix[0][1],2);6104 epsilon_sqr[1][1]=pow(epsilon_matrix[1][1],2);6105 epsilon_sqr[2][1]=pow(epsilon_matrix[2][1],2);6106 epsilon_sqr[0][2]=pow(epsilon_matrix[0][2],2);6107 epsilon_sqr[1][2]=pow(epsilon_matrix[1][2],2);6108 epsilon_sqr[2][2]=pow(epsilon_matrix[2][2],2);6109 6110 epsilon_eff=1/pow(2,0.5)*pow((epsilon_sqr[0][0]+epsilon_sqr[0][1]+ epsilon_sqr[0][2]+ epsilon_sqr[1][0]+ epsilon_sqr[1][1]+ epsilon_sqr[1][2]+ epsilon_sqr[2][0]+ epsilon_sqr[2][1]+ epsilon_sqr[2][2]),0.5);6111 *phi=2*pow(epsilon_eff,2.0)*viscosity;6112 }6113 /*}}}*/6114 /*FUNCTION Penta::GetStrainRate3dPattyn{{{1*/6115 void Penta::GetStrainRate3dPattyn(double* epsilon,double* xyz_list, double* gauss, Input* vx_input, Input* vy_input){6116 /*Compute the 3d Blatter/PattynStrain Rate (5 components):6117 *6118 * epsilon=[exx eyy exy exz eyz]6119 *6120 * with exz=1/2 du/dz6121 * eyz=1/2 dv/dz6122 *6123 * the contribution of vz is neglected6124 */6125 6126 int i;6127 6128 double epsilonvx[5];6129 double epsilonvy[5];6130 6131 /*Check that both inputs have been found*/6132 if (!vx_input || !vy_input){6133 ISSMERROR("Input missing. Here are the input pointers we have for vx: %p, vy: %p\n",vx_input,vy_input);6134 }6135 6136 /*Get strain rate assuming that epsilon has been allocated*/6137 vx_input->GetVxStrainRate3dPattyn(epsilonvx,xyz_list,gauss);6138 vy_input->GetVyStrainRate3dPattyn(epsilonvy,xyz_list,gauss);6139 6140 /*Sum all contributions*/6141 for(i=0;i<5;i++) epsilon[i]=epsilonvx[i]+epsilonvy[i];6142 6143 }6144 /*}}}*/6145 /*FUNCTION Penta::GetStrainRate3d{{{1*/6146 void Penta::GetStrainRate3d(double* epsilon,double* xyz_list, double* gauss, Input* vx_input, Input* vy_input, Input* vz_input){6147 /*Compute the 3d Strain Rate (6 components):6148 *6149 * epsilon=[exx eyy ezz exy exz eyz]6150 */6151 6152 int i;6153 6154 double epsilonvx[6];6155 double epsilonvy[6];6156 double epsilonvz[6];6157 6158 /*Check that both inputs have been found*/6159 if (!vx_input || !vy_input || !vz_input){6160 ISSMERROR("Input missing. Here are the input pointers we have for vx: %p, vy: %p, vz: %p\n",vx_input,vy_input,vz_input);6161 }6162 6163 /*Get strain rate assuming that epsilon has been allocated*/6164 vx_input->GetVxStrainRate3d(epsilonvx,xyz_list,gauss);6165 vy_input->GetVyStrainRate3d(epsilonvy,xyz_list,gauss);6166 vz_input->GetVzStrainRate3d(epsilonvz,xyz_list,gauss);6167 6168 /*Sum all contributions*/6169 for(i=0;i<6;i++) epsilon[i]=epsilonvx[i]+epsilonvy[i]+epsilonvz[i];6170 6171 }6172 /*}}}*/6173 /*FUNCTION Penta::GradjB {{{1*/6174 void Penta::GradjB(Vec gradient){6175 6176 int i;6177 Tria* tria=NULL;6178 TriaVertexInput* triavertexinput=NULL;6179 6180 /*inputs: */6181 bool onwater;6182 bool collapse;6183 bool onbed;6184 6185 /*retrieve inputs :*/6186 inputs->GetParameterValue(&onwater,ElementOnWaterEnum);6187 inputs->GetParameterValue(&collapse,CollapseEnum);6188 inputs->GetParameterValue(&onbed,ElementOnBedEnum);6189 6190 /*If on water, skip: */6191 if(onwater)return;6192 6193 if (collapse){6194 /*Bail out element if collapsed (2d) and not on bed*/6195 if (!onbed) return;6196 6197 /*This element should be collapsed into a tria element at its base. Create this tria element,6198 * and compute gardj*/6199 tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria (lower face).6200 tria->GradjB(gradient);6201 delete tria;6202 }6203 else{6204 /*B is a 2d field, use MacAyeal(2d) gradient even if it is Stokes or Pattyn*/6205 tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria (lower face).6206 tria->GradjB(gradient);6207 delete tria;6208 }6209 6210 6211 }6212 /*}}}*/6213 5156 /*FUNCTION Penta::ReduceMatrixStokes {{{1*/ 6214 5157 void Penta::ReduceMatrixStokes(double* Ke_reduced, double* Ke_temp){ … … 6305 5248 } 6306 5249 /*}}}1*/ 5250 /*FUNCTION Penta::SpawnTria {{{1*/ 5251 Tria* Penta::SpawnTria(int g0, int g1, int g2){ 5252 5253 int i; 5254 int analysis_counter; 5255 5256 /*go into parameters and get the analysis_counter: */ 5257 this->parameters->FindParam(&analysis_counter,AnalysisCounterEnum); 5258 5259 /*out of grids g0,g1 and g2 from Penta, build a tria element: */ 5260 Tria* tria=NULL; 5261 int indices[3]; 5262 int zero=0; 5263 Parameters* tria_parameters=NULL; 5264 Inputs* tria_inputs=NULL; 5265 Results* tria_results=NULL; 5266 5267 indices[0]=g0; 5268 indices[1]=g1; 5269 indices[2]=g2; 5270 5271 tria_parameters=this->parameters; 5272 tria_inputs=(Inputs*)this->inputs->SpawnTriaInputs(indices); 5273 tria_results=(Results*)this->results->SpawnTriaResults(indices); 5274 5275 tria=new Tria(); 5276 tria->id=this->id; 5277 tria->inputs=tria_inputs; 5278 tria->results=tria_results; 5279 tria->parameters=tria_parameters; 5280 tria->element_type=P1Enum; //Only P1 CG for now 5281 this->SpawnTriaHook(dynamic_cast<TriaHook*>(tria),&indices[0]); 5282 5283 /*recover nodes, matice and matpar: */ 5284 tria->nodes=(Node**)tria->hnodes[analysis_counter]->deliverp(); 5285 tria->matice=(Matice*)tria->hmatice->delivers(); 5286 tria->matpar=(Matpar*)tria->hmatpar->delivers(); 5287 5288 return tria; 5289 } 5290 /*}}}*/ 5291 /*FUNCTION Penta::SpawnBeam {{{1*/ 5292 void* Penta::SpawnBeam(int g0, int g1){ 5293 5294 int i; 5295 5296 /*out of grids g0,g1 and g2 from Penta, build a beam element: */ 5297 Beam* beam=NULL; 5298 int indices[2]; 5299 int zero=0; 5300 Parameters *beam_parameters = NULL; 5301 Inputs *beam_inputs = NULL; 5302 5303 indices[0]=g0; 5304 indices[1]=g1; 5305 5306 beam_parameters=this->parameters; 5307 beam_inputs=(Inputs*)this->inputs->SpawnBeamInputs(indices); 5308 5309 beam=new Beam(); 5310 beam->id=this->id; 5311 beam->inputs=beam_inputs; 5312 beam->parameters=beam_parameters; 5313 5314 /*now deal with ndoes,matice and matpar: */ 5315 beam->nodes=(Node**)xmalloc(2*sizeof(Node*)); 5316 for(i=0;i<2;i++)beam->nodes[i]=this->nodes[indices[i]]; 5317 beam->matice=this->matice; 5318 beam->matpar=this->matpar; 5319 5320 return beam; 5321 } 5322 /*}}}*/ 5323 /*FUNCTION Penta::SpawnSing {{{1*/ 5324 void* Penta::SpawnSing(int index){ 5325 5326 Sing* sing=NULL; 5327 int zero=0; 5328 Parameters *sing_parameters = NULL; 5329 Inputs *sing_inputs = NULL; 5330 5331 sing_parameters=this->parameters; 5332 sing_inputs=(Inputs*)this->inputs->SpawnSingInputs(index); 5333 5334 sing=new Sing(); 5335 sing->id=this->id; 5336 sing->inputs=sing_inputs; 5337 sing->parameters=sing_parameters; 5338 5339 /*now deal with nodes,matice and matpar: */ 5340 sing->node=this->nodes[index]; 5341 sing->matice=this->matice; 5342 sing->matpar=this->matpar; 5343 5344 return sing; 5345 } 5346 /*}}}*/ 6307 5347 /*FUNCTION Penta::SurfaceNormal {{{1*/ 6308 5348 void Penta::SurfaceNormal(double* surface_normal, double xyz_list[3][3]){ … … 6331 5371 } 6332 5372 /*}}}*/ 5373 /*FUNCTION Penta::VecExtrude {{{1*/ 5374 void Penta::VecExtrude(Vec vector,double* vector_serial,int iscollapsed){ 5375 5376 /* node data: */ 5377 int i; 5378 Node* node=NULL; 5379 int extrude=0; 5380 5381 /*inputs: */ 5382 bool collapse; 5383 bool onbed; 5384 5385 /*retrieve inputs :*/ 5386 inputs->GetParameterValue(&collapse,CollapseEnum); 5387 inputs->GetParameterValue(&onbed,ElementOnBedEnum); 5388 5389 /*Figure out if we should extrude for this element: */ 5390 if (iscollapsed){ 5391 /*From higher level, we are told to extrude only elements that have the collapse flag on: */ 5392 if (collapse)extrude=1; 5393 else extrude=0; 5394 } 5395 else{ 5396 /*From higher level, we are told to extrude all elements: */ 5397 extrude=1; 5398 } 5399 5400 /*Now, extrusion starts from the bed on, so double check this element is on 5401 * the bedrock: */ 5402 if(onbed==0)extrude=0; 5403 5404 /*Go on and extrude vector: */ 5405 if (extrude){ 5406 5407 /* node data: */ 5408 int dof1; 5409 double vectorel; 5410 5411 /*this penta is a collapsed macayeal. For each node on the base of this penta, 5412 * we grab the vector. Once we know the vector, we follow the upper nodes, 5413 * inserting the same vector value into vector, until we reach the surface: */ 5414 for(i=0;i<3;i++){ 5415 5416 node=nodes[i]; //base nodes 5417 dof1=node->GetDofList1(); 5418 5419 /*get vector for this base node: */ 5420 vectorel=vector_serial[dof1]; 5421 5422 //go throvectorn all nodes which sit on top of this node, until we reach the surface, 5423 //and plvector vector in vector 5424 for(;;){ 5425 5426 dof1=node->GetDofList1(); 5427 VecSetValues(vector,1,&dof1,&vectorel,INSERT_VALUES); 5428 5429 if (node->IsOnSurface())break; 5430 /*get next node: */ 5431 node=node->GetUpperNode(); 5432 } 5433 } 5434 } 5435 } 5436 /*}}}*/ -
issm/trunk/src/c/objects/Elements/Penta.h
r4882 r4885 136 136 void CreatePVectorSlope( Vec pg); 137 137 void CreatePVectorThermal( Vec pg); 138 double* GaussFromNode(Node* node); 139 void GetB(double* pB, double* xyz_list, double* gauss_coord); 140 void GetBPrime(double* B, double* xyz_list, double* gauss_coord); 141 void GetBPrime_vert(double* B, double* xyz_list, double* gauss_coord); 142 void GetBStokes(double* B, double* xyz_list, double* gauss_coord); 143 void GetB_advec(double* B_advec, double* xyz_list, double* gauss_coord); 144 void GetB_artdiff(double* B_artdiff, double* xyz_list, double* gauss_coord); 145 void GetB_conduct(double* B_conduct, double* xyz_list, double* gauss_coord); 146 void GetB_vert(double* B, double* xyz_list, double* gauss_coord); 147 void GetBprimeStokes(double* B_prime, double* xyz_list, double* gauss_coord); 148 void GetBprime_advec(double* Bprime_advec, double* xyz_list, double* gauss_coord); 138 double* GaussFromNode(Node* node); 149 139 void GetDofList(int* doflist,int* pnumberofdofs); 150 140 void GetDofList1(int* doflist); 151 void GetJacobian(double* J, double* xyz_list,double* gauss_coord); 152 void GetJacobianDeterminant(double* Jdet, double* xyz_list,double* gauss_coord); 153 void GetJacobianInvert(double* Jinv, double* xyz_list,double* gauss_coord); 154 void GetLStokes(double* LStokes, double* gauss_coord_tria); 155 void GetLprimeStokes(double* LprimeStokes, double* xyz_list, double* gauss_coord_tria, double* gauss_coord); 141 int GetElementType(void); 156 142 void GetMatrixInvert(double* Ke_invert, double* Ke); 157 143 void GetNodalFunctions(double* l1l6, double* gauss_coord); … … 161 147 void GetNodalFunctionsDerivativesStokes(double* dh1dh7,double* xyz_list, double* gauss_coord); 162 148 void GetNodalFunctionsStokes(double* l1l7, double* gauss_coord); 163 void GetParameterDerivativeValue(double* p, double* p_list,double* xyz_list, double* gauss_coord);164 149 void GetParameterValue(double* pvalue, double* v_list,double* gauss_coord); 165 150 void GetParameterValue(double* pvalue,Node* node,int enumtype); -
issm/trunk/src/c/objects/Elements/PentaRef.cpp
r4882 r4885 52 52 53 53 /*Reference Element numerics*/ 54 /*FUNCTION PentaRef::GetBPattyn {{{1*/ 55 void PentaRef::GetBPattyn(double* B, double* xyz_list, double* gauss){ 56 /*Compute B matrix. B=[B1 B2 B3 B4 B5 B6] where Bi is of size 5*NDOF2. 57 * For grid i, Bi can be expressed in the actual coordinate system 58 * by: 59 * Bi=[ dh/dx 0 ] 60 * [ 0 dh/dy ] 61 * [ 1/2*dh/dy 1/2*dh/dx ] 62 * [ 1/2*dh/dz 0 ] 63 * [ 0 1/2*dh/dz ] 64 * where h is the interpolation function for grid i. 65 * 66 * We assume B has been allocated already, of size: 5x(NDOF2*numgrids) 67 */ 68 69 int i; 70 const int numgrids=6; 71 const int NDOF3=3; 72 const int NDOF2=2; 73 74 double dh1dh6[NDOF3][numgrids]; 75 76 /*Get dh1dh6 in actual coordinate system: */ 77 GetNodalFunctionsP1Derivatives(&dh1dh6[0][0],xyz_list, gauss); 78 79 /*Build B: */ 80 for (i=0;i<numgrids;i++){ 81 *(B+NDOF2*numgrids*0+NDOF2*i)=dh1dh6[0][i]; 82 *(B+NDOF2*numgrids*0+NDOF2*i+1)=0.0; 83 84 *(B+NDOF2*numgrids*1+NDOF2*i)=0.0; 85 *(B+NDOF2*numgrids*1+NDOF2*i+1)=dh1dh6[1][i]; 86 87 *(B+NDOF2*numgrids*2+NDOF2*i)=(float).5*dh1dh6[1][i]; 88 *(B+NDOF2*numgrids*2+NDOF2*i+1)=(float).5*dh1dh6[0][i]; 89 90 *(B+NDOF2*numgrids*3+NDOF2*i)=(float).5*dh1dh6[2][i]; 91 *(B+NDOF2*numgrids*3+NDOF2*i+1)=0.0; 92 93 *(B+NDOF2*numgrids*4+NDOF2*i)=0.0; 94 *(B+NDOF2*numgrids*4+NDOF2*i+1)=(float).5*dh1dh6[2][i]; 95 } 96 97 } 98 /*}}}*/ 99 /*FUNCTION PentaRef::GetBprimePattyn {{{1*/ 100 void PentaRef::GetBprimePattyn(double* B, double* xyz_list, double* gauss_coord){ 101 /*Compute B prime matrix. B=[B1 B2 B3 B4 B5 B6] where Bi is of size 5*NDOF2. 102 * For grid i, Bi can be expressed in the actual coordinate system 103 * by: 104 * Bi=[ 2*dh/dx dh/dy ] 105 * [ dh/dx 2*dh/dy ] 106 * [ dh/dy dh/dx ] 107 * [ dh/dz 0 ] 108 * [ 0 dh/dz ] 109 * where h is the interpolation function for grid i. 110 * 111 * We assume B has been allocated already, of size: 5x(NDOF2*numgrids) 112 */ 113 114 int i; 115 const int NDOF3=3; 116 const int NDOF2=2; 117 const int numgrids=6; 118 119 double dh1dh6[NDOF3][numgrids]; 120 121 /*Get dh1dh6 in actual coordinate system: */ 122 GetNodalFunctionsP1Derivatives(&dh1dh6[0][0],xyz_list, gauss_coord); 123 124 /*Build BPrime: */ 125 for (i=0;i<numgrids;i++){ 126 *(B+NDOF2*numgrids*0+NDOF2*i)=2.0*dh1dh6[0][i]; 127 *(B+NDOF2*numgrids*0+NDOF2*i+1)=dh1dh6[1][i]; 128 129 *(B+NDOF2*numgrids*1+NDOF2*i)=dh1dh6[0][i]; 130 *(B+NDOF2*numgrids*1+NDOF2*i+1)=2.0*dh1dh6[1][i]; 131 132 *(B+NDOF2*numgrids*2+NDOF2*i)=dh1dh6[1][i]; 133 *(B+NDOF2*numgrids*2+NDOF2*i+1)=dh1dh6[0][i]; 134 135 *(B+NDOF2*numgrids*3+NDOF2*i)=dh1dh6[2][i]; 136 *(B+NDOF2*numgrids*3+NDOF2*i+1)=0.0; 137 138 *(B+NDOF2*numgrids*4+NDOF2*i)=0.0; 139 *(B+NDOF2*numgrids*4+NDOF2*i+1)=dh1dh6[2][i]; 140 } 141 } 142 /*}}}*/ 143 /*FUNCTION PentaRef::GetBStokes {{{1*/ 144 void PentaRef::GetBStokes(double* B, double* xyz_list, double* gauss){ 145 146 /*Compute B matrix. B=[B1 B2 B3 B4 B5 B6] where Bi is of size 3*DOFPERGRID. 147 * For grid i, Bi can be expressed in the actual coordinate system 148 * by: Bi=[ dh/dx 0 0 0 ] 149 * [ 0 dh/dy 0 0 ] 150 * [ 0 0 dh/dy 0 ] 151 * [ 1/2*dh/dy 1/2*dh/dx 0 0 ] 152 * [ 1/2*dh/dz 0 1/2*dh/dx 0 ] 153 * [ 0 1/2*dh/dz 1/2*dh/dy 0 ] 154 * [ 0 0 0 h ] 155 * [ dh/dx dh/dy dh/dz 0 ] 156 * where h is the interpolation function for grid i. 157 * Same thing for Bb except the last column that does not exist. 158 */ 159 160 int i; 161 const int calculationdof=3; 162 const int numgrids=6; 163 int DOFPERGRID=4; 164 165 double dh1dh7[calculationdof][numgrids+1]; 166 double l1l6[numgrids]; 167 168 169 /*Get dh1dh7 in actual coordinate system: */ 170 GetNodalFunctionsMINIDerivatives(&dh1dh7[0][0],xyz_list, gauss); 171 GetNodalFunctionsP1(l1l6, gauss); 172 173 /*Build B: */ 174 for (i=0;i<numgrids+1;i++){ 175 *(B+(DOFPERGRID*numgrids+3)*0+DOFPERGRID*i)=dh1dh7[0][i]; //B[0][DOFPERGRID*i]=dh1dh6[0][i]; 176 *(B+(DOFPERGRID*numgrids+3)*0+DOFPERGRID*i+1)=0; 177 *(B+(DOFPERGRID*numgrids+3)*0+DOFPERGRID*i+2)=0; 178 *(B+(DOFPERGRID*numgrids+3)*1+DOFPERGRID*i)=0; 179 *(B+(DOFPERGRID*numgrids+3)*1+DOFPERGRID*i+1)=dh1dh7[1][i]; 180 *(B+(DOFPERGRID*numgrids+3)*1+DOFPERGRID*i+2)=0; 181 *(B+(DOFPERGRID*numgrids+3)*2+DOFPERGRID*i)=0; 182 *(B+(DOFPERGRID*numgrids+3)*2+DOFPERGRID*i+1)=0; 183 *(B+(DOFPERGRID*numgrids+3)*2+DOFPERGRID*i+2)=dh1dh7[2][i]; 184 *(B+(DOFPERGRID*numgrids+3)*3+DOFPERGRID*i)=(float).5*dh1dh7[1][i]; 185 *(B+(DOFPERGRID*numgrids+3)*3+DOFPERGRID*i+1)=(float).5*dh1dh7[0][i]; 186 *(B+(DOFPERGRID*numgrids+3)*3+DOFPERGRID*i+2)=0; 187 *(B+(DOFPERGRID*numgrids+3)*4+DOFPERGRID*i)=(float).5*dh1dh7[2][i]; 188 *(B+(DOFPERGRID*numgrids+3)*4+DOFPERGRID*i+1)=0; 189 *(B+(DOFPERGRID*numgrids+3)*4+DOFPERGRID*i+2)=(float).5*dh1dh7[0][i]; 190 *(B+(DOFPERGRID*numgrids+3)*5+DOFPERGRID*i)=0; 191 *(B+(DOFPERGRID*numgrids+3)*5+DOFPERGRID*i+1)=(float).5*dh1dh7[2][i]; 192 *(B+(DOFPERGRID*numgrids+3)*5+DOFPERGRID*i+2)=(float).5*dh1dh7[1][i]; 193 *(B+(DOFPERGRID*numgrids+3)*6+DOFPERGRID*i)=0; 194 *(B+(DOFPERGRID*numgrids+3)*6+DOFPERGRID*i+1)=0; 195 *(B+(DOFPERGRID*numgrids+3)*6+DOFPERGRID*i+2)=0; 196 *(B+(DOFPERGRID*numgrids+3)*7+DOFPERGRID*i)=dh1dh7[0][i]; 197 *(B+(DOFPERGRID*numgrids+3)*7+DOFPERGRID*i+1)=dh1dh7[1][i]; 198 *(B+(DOFPERGRID*numgrids+3)*7+DOFPERGRID*i+2)=dh1dh7[2][i]; 199 } 200 201 for (i=0;i<numgrids;i++){ //last column not for the bubble function 202 *(B+(DOFPERGRID*numgrids+3)*0+DOFPERGRID*i+3)=0; 203 *(B+(DOFPERGRID*numgrids+3)*1+DOFPERGRID*i+3)=0; 204 *(B+(DOFPERGRID*numgrids+3)*2+DOFPERGRID*i+3)=0; 205 *(B+(DOFPERGRID*numgrids+3)*3+DOFPERGRID*i+3)=0; 206 *(B+(DOFPERGRID*numgrids+3)*4+DOFPERGRID*i+3)=0; 207 *(B+(DOFPERGRID*numgrids+3)*5+DOFPERGRID*i+3)=0; 208 *(B+(DOFPERGRID*numgrids+3)*6+DOFPERGRID*i+3)=l1l6[i]; 209 *(B+(DOFPERGRID*numgrids+3)*7+DOFPERGRID*i+3)=0; 210 } 211 212 } 213 /*}}}*/ 214 /*FUNCTION PentaRef::GetBprimeStokes {{{1*/ 215 void PentaRef::GetBprimeStokes(double* B_prime, double* xyz_list, double* gauss){ 216 /* Compute B' matrix. B'=[B1' B2' B3' B4' B5' B6' Bb'] where Bi' is of size 3*NDOF2. 217 * For grid i, Bi' can be expressed in the actual coordinate system 218 * by: 219 * Bi'=[ dh/dx 0 0 0] 220 * [ 0 dh/dy 0 0] 221 * [ 0 0 dh/dz 0] 222 * [ dh/dy dh/dx 0 0] 223 * [ dh/dz 0 dh/dx 0] 224 * [ 0 dh/dz dh/dy 0] 225 * [ dh/dx dh/dy dh/dz 0] 226 * [ 0 0 0 h] 227 * where h is the interpolation function for grid i. 228 * 229 * Same thing for the bubble fonction except that there is no fourth column 230 */ 231 232 int i; 233 const int calculationdof=3; 234 const int numgrids=6; 235 int DOFPERGRID=4; 236 237 double dh1dh7[calculationdof][numgrids+1]; 238 double l1l6[numgrids]; 239 240 /*Get dh1dh7 in actual coordinate system: */ 241 GetNodalFunctionsMINIDerivatives(&dh1dh7[0][0],xyz_list, gauss); 242 243 GetNodalFunctionsP1(l1l6, gauss); 244 245 /*B_primeuild B_prime: */ 246 for (i=0;i<numgrids+1;i++){ 247 *(B_prime+(DOFPERGRID*numgrids+3)*0+DOFPERGRID*i)=dh1dh7[0][i]; //B_prime[0][DOFPERGRID*i]=dh1dh6[0][i]; 248 *(B_prime+(DOFPERGRID*numgrids+3)*0+DOFPERGRID*i+1)=0; 249 *(B_prime+(DOFPERGRID*numgrids+3)*0+DOFPERGRID*i+2)=0; 250 *(B_prime+(DOFPERGRID*numgrids+3)*1+DOFPERGRID*i)=0; 251 *(B_prime+(DOFPERGRID*numgrids+3)*1+DOFPERGRID*i+1)=dh1dh7[1][i]; 252 *(B_prime+(DOFPERGRID*numgrids+3)*1+DOFPERGRID*i+2)=0; 253 *(B_prime+(DOFPERGRID*numgrids+3)*2+DOFPERGRID*i)=0; 254 *(B_prime+(DOFPERGRID*numgrids+3)*2+DOFPERGRID*i+1)=0; 255 *(B_prime+(DOFPERGRID*numgrids+3)*2+DOFPERGRID*i+2)=dh1dh7[2][i]; 256 *(B_prime+(DOFPERGRID*numgrids+3)*3+DOFPERGRID*i)=dh1dh7[1][i]; 257 *(B_prime+(DOFPERGRID*numgrids+3)*3+DOFPERGRID*i+1)=dh1dh7[0][i]; 258 *(B_prime+(DOFPERGRID*numgrids+3)*3+DOFPERGRID*i+2)=0; 259 *(B_prime+(DOFPERGRID*numgrids+3)*4+DOFPERGRID*i)=dh1dh7[2][i]; 260 *(B_prime+(DOFPERGRID*numgrids+3)*4+DOFPERGRID*i+1)=0; 261 *(B_prime+(DOFPERGRID*numgrids+3)*4+DOFPERGRID*i+2)=dh1dh7[0][i]; 262 *(B_prime+(DOFPERGRID*numgrids+3)*5+DOFPERGRID*i)=0; 263 *(B_prime+(DOFPERGRID*numgrids+3)*5+DOFPERGRID*i+1)=dh1dh7[2][i]; 264 *(B_prime+(DOFPERGRID*numgrids+3)*5+DOFPERGRID*i+2)=dh1dh7[1][i]; 265 *(B_prime+(DOFPERGRID*numgrids+3)*6+DOFPERGRID*i)=dh1dh7[0][i]; 266 *(B_prime+(DOFPERGRID*numgrids+3)*6+DOFPERGRID*i+1)=dh1dh7[1][i]; 267 *(B_prime+(DOFPERGRID*numgrids+3)*6+DOFPERGRID*i+2)=dh1dh7[2][i]; 268 *(B_prime+(DOFPERGRID*numgrids+3)*7+DOFPERGRID*i)=0; 269 *(B_prime+(DOFPERGRID*numgrids+3)*7+DOFPERGRID*i+1)=0; 270 *(B_prime+(DOFPERGRID*numgrids+3)*7+DOFPERGRID*i+2)=0; 271 } 272 273 for (i=0;i<numgrids;i++){ //last column not for the bubble function 274 *(B_prime+(DOFPERGRID*numgrids+3)*0+DOFPERGRID*i+3)=0; 275 *(B_prime+(DOFPERGRID*numgrids+3)*1+DOFPERGRID*i+3)=0; 276 *(B_prime+(DOFPERGRID*numgrids+3)*2+DOFPERGRID*i+3)=0; 277 *(B_prime+(DOFPERGRID*numgrids+3)*3+DOFPERGRID*i+3)=0; 278 *(B_prime+(DOFPERGRID*numgrids+3)*4+DOFPERGRID*i+3)=0; 279 *(B_prime+(DOFPERGRID*numgrids+3)*5+DOFPERGRID*i+3)=0; 280 *(B_prime+(DOFPERGRID*numgrids+3)*6+DOFPERGRID*i+3)=0; 281 *(B_prime+(DOFPERGRID*numgrids+3)*7+DOFPERGRID*i+3)=l1l6[i]; 282 } 283 284 } 285 /*}}}*/ 286 /*FUNCTION PentaRef::GetBArtdiff {{{1*/ 287 void PentaRef::GetBArtdiff(double* B_artdiff, double* xyz_list, double* gauss){ 288 /*Compute B matrix. B=[B1 B2 B3 B4 B5 B6] where Bi is of size 5*DOFPERGRID. 289 * For grid i, Bi' can be expressed in the actual coordinate system 290 * by: 291 * Bi_artdiff=[ dh/dx ] 292 * [ dh/dy ] 293 * where h is the interpolation function for grid i. 294 * 295 * We assume B has been allocated already, of size: 2x(DOFPERGRID*numgrids) 296 */ 297 298 int i; 299 const int calculationdof=3; 300 const int numgrids=6; 301 int DOFPERGRID=1; 302 303 /*Same thing in the actual coordinate system: */ 304 double dh1dh6[calculationdof][numgrids]; 305 306 /*Get dh1dh6 in actual coordinates system : */ 307 GetNodalFunctionsP1Derivatives(&dh1dh6[0][0],xyz_list,gauss); 308 309 /*Build B': */ 310 for (i=0;i<numgrids;i++){ 311 *(B_artdiff+DOFPERGRID*numgrids*0+DOFPERGRID*i)=dh1dh6[0][i]; 312 *(B_artdiff+DOFPERGRID*numgrids*1+DOFPERGRID*i)=dh1dh6[1][i]; 313 } 314 } 315 /*}}}*/ 316 /*FUNCTION PentaRef::GetBAdvec{{{1*/ 317 void PentaRef::GetBAdvec(double* B_advec, double* xyz_list, double* gauss){ 318 /*Compute B matrix. B=[B1 B2 B3 B4 B5 B6] where Bi is of size 5*DOFPERGRID. 319 * For grid i, Bi' can be expressed in the actual coordinate system 320 * by: 321 * Bi_advec =[ h ] 322 * [ h ] 323 * [ h ] 324 * where h is the interpolation function for grid i. 325 * 326 * We assume B has been allocated already, of size: 3x(DOFPERGRID*numgrids) 327 */ 328 329 int i; 330 int calculationdof=3; 331 int numgrids=6; 332 int DOFPERGRID=1; 333 334 /*Same thing in the actual coordinate system: */ 335 double l1l6[6]; 336 337 /*Get dh1dh2dh3 in actual coordinates system : */ 338 GetNodalFunctionsP1(l1l6, gauss); 339 340 /*Build B': */ 341 for (i=0;i<numgrids;i++){ 342 *(B_advec+DOFPERGRID*numgrids*0+DOFPERGRID*i)=l1l6[i]; 343 *(B_advec+DOFPERGRID*numgrids*1+DOFPERGRID*i)=l1l6[i]; 344 *(B_advec+DOFPERGRID*numgrids*2+DOFPERGRID*i)=l1l6[i]; 345 } 346 } 347 /*}}}*/ 348 /*FUNCTION PentaRef::GetBConduct{{{1*/ 349 void PentaRef::GetBConduct(double* B_conduct, double* xyz_list, double* gauss){ 350 /*Compute B matrix. B=[B1 B2 B3 B4 B5 B6] where Bi is of size 5*DOFPERGRID. 351 * For grid i, Bi' can be expressed in the actual coordinate system 352 * by: 353 * Bi_conduct=[ dh/dx ] 354 * [ dh/dy ] 355 * [ dh/dz ] 356 * where h is the interpolation function for grid i. 357 * 358 * We assume B has been allocated already, of size: 3x(DOFPERGRID*numgrids) 359 */ 360 361 int i; 362 const int calculationdof=3; 363 const int numgrids=6; 364 int DOFPERGRID=1; 365 366 /*Same thing in the actual coordinate system: */ 367 double dh1dh6[calculationdof][numgrids]; 368 369 /*Get dh1dh2dh3 in actual coordinates system : */ 370 GetNodalFunctionsP1Derivatives(&dh1dh6[0][0],xyz_list,gauss); 371 372 /*Build B': */ 373 for (i=0;i<numgrids;i++){ 374 *(B_conduct+DOFPERGRID*numgrids*0+DOFPERGRID*i)=dh1dh6[0][i]; 375 *(B_conduct+DOFPERGRID*numgrids*1+DOFPERGRID*i)=dh1dh6[1][i]; 376 *(B_conduct+DOFPERGRID*numgrids*2+DOFPERGRID*i)=dh1dh6[2][i]; 377 } 378 } 379 /*}}}*/ 380 /*FUNCTION PentaRef::GetBVert{{{1*/ 381 void PentaRef::GetBVert(double* B, double* xyz_list, double* gauss){ 382 /* Compute B matrix. B=[dh1/dz dh2/dz dh3/dz dh4/dz dh5/dz dh6/dz]; 383 where hi is the interpolation function for grid i.*/ 384 385 int i; 386 const int NDOF3=3; 387 const int numgrids=6; 388 double dh1dh6[NDOF3][numgrids]; 389 390 /*Get dh1dh6 in actual coordinate system: */ 391 GetNodalFunctionsP1Derivatives(&dh1dh6[0][0],xyz_list, gauss); 392 393 /*Build B: */ 394 for (i=0;i<numgrids;i++){ 395 B[i]=dh1dh6[2][i]; 396 } 397 398 } 399 /*}}}*/ 400 /*FUNCTION PentaRef::GetBprimeAdvec{{{1*/ 401 void PentaRef::GetBprimeAdvec(double* Bprime_advec, double* xyz_list, double* gauss){ 402 /*Compute B matrix. B=[B1 B2 B3 B4 B5 B6] where Bi is of size 5*DOFPERGRID. 403 * For grid i, Bi' can be expressed in the actual coordinate system 404 * by: 405 * Biprime_advec=[ dh/dx ] 406 * [ dh/dy ] 407 * [ dh/dz ] 408 * where h is the interpolation function for grid i. 409 * 410 * We assume B has been allocated already, of size: 3x(DOFPERGRID*numgrids) 411 */ 412 413 int i; 414 const int calculationdof=3; 415 const int numgrids=6; 416 int DOFPERGRID=1; 417 418 /*Same thing in the actual coordinate system: */ 419 double dh1dh6[calculationdof][numgrids]; 420 421 /*Get dh1dh2dh3 in actual coordinates system : */ 422 GetNodalFunctionsP1Derivatives(&dh1dh6[0][0],xyz_list,gauss); 423 424 /*Build B': */ 425 for (i=0;i<numgrids;i++){ 426 *(Bprime_advec+DOFPERGRID*numgrids*0+DOFPERGRID*i)=dh1dh6[0][i]; 427 *(Bprime_advec+DOFPERGRID*numgrids*1+DOFPERGRID*i)=dh1dh6[1][i]; 428 *(Bprime_advec+DOFPERGRID*numgrids*2+DOFPERGRID*i)=dh1dh6[2][i]; 429 } 430 } 431 /*}}}*/ 432 /*FUNCTION PentaRef::GetBprimeVert{{{1*/ 433 void PentaRef::GetBprimeVert(double* B, double* xyz_list, double* gauss){ 434 /* Compute Bprime matrix. Bprime=[L1 L2 L3 L4 L5 L6] where Li is the nodal function for grid i*/ 435 436 GetNodalFunctionsP1(B, gauss); 437 438 } 439 /*}}}*/ 440 /*FUNCTION PentaRef::GetLStokes {{{1*/ 441 void PentaRef::GetLStokes(double* LStokes, double* gauss_tria){ 442 /* 443 * Compute L matrix. L=[L1 L2 L3] where Li is square and of size numdof. 444 * For grid i, Li can be expressed in the actual coordinate system 445 * by: 446 * Li=[ h 0 0 0] 447 * [ 0 h 0 0] 448 * [ 0 0 h 0] 449 * [ 0 0 h 0] 450 * [ h 0 0 0] 451 * [ 0 h 0 0] 452 * [ h 0 0 0] 453 * [ 0 h 0 0] 454 * [ 0 0 h 0] 455 * [ 0 0 h 0] 456 * [ 0 0 h 0] 457 * [ h 0 0 0] 458 * [ 0 h 0 0] 459 * [ 0 0 h 0] 460 * where h is the interpolation function for grid i. 461 */ 462 463 int i; 464 const int numgrids2d=3; 465 int num_dof=4; 466 467 double l1l2l3[numgrids2d]; 468 469 470 /*Get l1l2l3 in actual coordinate system: */ 471 l1l2l3[0]=gauss_tria[0]; 472 l1l2l3[1]=gauss_tria[1]; 473 l1l2l3[2]=gauss_tria[2]; 474 475 /*Build LStokes: */ 476 for (i=0;i<3;i++){ 477 *(LStokes+num_dof*numgrids2d*0+num_dof*i)=l1l2l3[i]; //LStokes[0][NDOF2*i]=dh1dh3[0][i]; 478 *(LStokes+num_dof*numgrids2d*0+num_dof*i+1)=0; 479 *(LStokes+num_dof*numgrids2d*0+num_dof*i+2)=0; 480 *(LStokes+num_dof*numgrids2d*0+num_dof*i+3)=0; 481 *(LStokes+num_dof*numgrids2d*1+num_dof*i)=0; 482 *(LStokes+num_dof*numgrids2d*1+num_dof*i+1)=l1l2l3[i]; 483 *(LStokes+num_dof*numgrids2d*1+num_dof*i+2)=0; 484 *(LStokes+num_dof*numgrids2d*1+num_dof*i+3)=0; 485 *(LStokes+num_dof*numgrids2d*2+num_dof*i)=0; 486 *(LStokes+num_dof*numgrids2d*2+num_dof*i+1)=0; 487 *(LStokes+num_dof*numgrids2d*2+num_dof*i+2)=l1l2l3[i]; 488 *(LStokes+num_dof*numgrids2d*2+num_dof*i+3)=0; 489 *(LStokes+num_dof*numgrids2d*3+num_dof*i)=0; 490 *(LStokes+num_dof*numgrids2d*3+num_dof*i+1)=0; 491 *(LStokes+num_dof*numgrids2d*3+num_dof*i+2)=l1l2l3[i]; 492 *(LStokes+num_dof*numgrids2d*3+num_dof*i+3)=0; 493 *(LStokes+num_dof*numgrids2d*4+num_dof*i)=l1l2l3[i]; 494 *(LStokes+num_dof*numgrids2d*4+num_dof*i+1)=0; 495 *(LStokes+num_dof*numgrids2d*4+num_dof*i+2)=0; 496 *(LStokes+num_dof*numgrids2d*4+num_dof*i+3)=0; 497 *(LStokes+num_dof*numgrids2d*5+num_dof*i)=0; 498 *(LStokes+num_dof*numgrids2d*5+num_dof*i+1)=l1l2l3[i]; 499 *(LStokes+num_dof*numgrids2d*5+num_dof*i+2)=0; 500 *(LStokes+num_dof*numgrids2d*5+num_dof*i+3)=0; 501 *(LStokes+num_dof*numgrids2d*6+num_dof*i)=l1l2l3[i]; 502 *(LStokes+num_dof*numgrids2d*6+num_dof*i+1)=0; 503 *(LStokes+num_dof*numgrids2d*6+num_dof*i+2)=0; 504 *(LStokes+num_dof*numgrids2d*6+num_dof*i+3)=0; 505 *(LStokes+num_dof*numgrids2d*7+num_dof*i)=0; 506 *(LStokes+num_dof*numgrids2d*7+num_dof*i+1)=l1l2l3[i]; 507 *(LStokes+num_dof*numgrids2d*7+num_dof*i+2)=0; 508 *(LStokes+num_dof*numgrids2d*7+num_dof*i+3)=0; 509 *(LStokes+num_dof*numgrids2d*8+num_dof*i)=0; 510 *(LStokes+num_dof*numgrids2d*8+num_dof*i+1)=0; 511 *(LStokes+num_dof*numgrids2d*8+num_dof*i+2)=l1l2l3[i]; 512 *(LStokes+num_dof*numgrids2d*8+num_dof*i+3)=0; 513 *(LStokes+num_dof*numgrids2d*9+num_dof*i)=0; 514 *(LStokes+num_dof*numgrids2d*9+num_dof*i+1)=0; 515 *(LStokes+num_dof*numgrids2d*9+num_dof*i+2)=l1l2l3[i]; 516 *(LStokes+num_dof*numgrids2d*9+num_dof*i+3)=0; 517 *(LStokes+num_dof*numgrids2d*10+num_dof*i)=0; 518 *(LStokes+num_dof*numgrids2d*10+num_dof*i+1)=0; 519 *(LStokes+num_dof*numgrids2d*10+num_dof*i+2)=l1l2l3[i]; 520 *(LStokes+num_dof*numgrids2d*10+num_dof*i+3)=0; 521 *(LStokes+num_dof*numgrids2d*11+num_dof*i)=l1l2l3[i]; 522 *(LStokes+num_dof*numgrids2d*11+num_dof*i+1)=0; 523 *(LStokes+num_dof*numgrids2d*11+num_dof*i+2)=0; 524 *(LStokes+num_dof*numgrids2d*11+num_dof*i+3)=0; 525 *(LStokes+num_dof*numgrids2d*12+num_dof*i)=0; 526 *(LStokes+num_dof*numgrids2d*12+num_dof*i+1)=l1l2l3[i]; 527 *(LStokes+num_dof*numgrids2d*12+num_dof*i+2)=0; 528 *(LStokes+num_dof*numgrids2d*12+num_dof*i+3)=0; 529 *(LStokes+num_dof*numgrids2d*13+num_dof*i)=0; 530 *(LStokes+num_dof*numgrids2d*13+num_dof*i+1)=0; 531 *(LStokes+num_dof*numgrids2d*13+num_dof*i+2)=l1l2l3[i]; 532 *(LStokes+num_dof*numgrids2d*13+num_dof*i+3)=0; 533 534 } 535 } 536 /*}}}*/ 537 /*FUNCTION PentaRef::GetLprimeStokes {{{1*/ 538 void PentaRef::GetLprimeStokes(double* LprimeStokes, double* xyz_list, double* gauss_tria, double* gauss){ 539 540 /* 541 * Compute Lprime matrix. Lprime=[Lp1 Lp2 Lp3] where Lpi is square and of size numdof. 542 * For grid i, Lpi can be expressed in the actual coordinate system 543 * by: 544 * Lpi=[ h 0 0 0] 545 * [ 0 h 0 0] 546 * [ h 0 0 0] 547 * [ 0 h 0 0] 548 * [ 0 0 h 0] 549 * [ 0 0 h 0] 550 * [ 0 0 dh/dz 0] 551 * [ 0 0 dh/dz 0] 552 * [ 0 0 dh/dz 0] 553 * [dh/dz 0 dh/dx 0] 554 * [ 0 dh/dz dh/dy 0] 555 * [ 0 0 0 h] 556 * [ 0 0 0 h] 557 * [ 0 0 0 h] 558 * where h is the interpolation function for grid i. 559 */ 560 int i; 561 const int numgrids2d=3; 562 int num_dof=4; 563 564 double l1l2l3[numgrids2d]; 565 double dh1dh6[3][6]; 566 567 /*Get l1l2l3 in actual coordinate system: */ 568 l1l2l3[0]=gauss_tria[0]; 569 l1l2l3[1]=gauss_tria[1]; 570 l1l2l3[2]=gauss_tria[2]; 571 572 GetNodalFunctionsP1Derivatives(&dh1dh6[0][0],xyz_list,gauss); 573 574 /*Build LprimeStokes: */ 575 for (i=0;i<3;i++){ 576 *(LprimeStokes+num_dof*numgrids2d*0+num_dof*i)=l1l2l3[i]; //LprimeStokes[0][NDOF2*i]=dh1dh3[0][i]; 577 *(LprimeStokes+num_dof*numgrids2d*0+num_dof*i+1)=0; 578 *(LprimeStokes+num_dof*numgrids2d*0+num_dof*i+2)=0; 579 *(LprimeStokes+num_dof*numgrids2d*0+num_dof*i+3)=0; 580 *(LprimeStokes+num_dof*numgrids2d*1+num_dof*i)=0; 581 *(LprimeStokes+num_dof*numgrids2d*1+num_dof*i+1)=l1l2l3[i]; 582 *(LprimeStokes+num_dof*numgrids2d*1+num_dof*i+2)=0; 583 *(LprimeStokes+num_dof*numgrids2d*1+num_dof*i+3)=0; 584 *(LprimeStokes+num_dof*numgrids2d*2+num_dof*i)=l1l2l3[i]; 585 *(LprimeStokes+num_dof*numgrids2d*2+num_dof*i+1)=0; 586 *(LprimeStokes+num_dof*numgrids2d*2+num_dof*i+2)=0; 587 *(LprimeStokes+num_dof*numgrids2d*2+num_dof*i+3)=0; 588 *(LprimeStokes+num_dof*numgrids2d*3+num_dof*i)=0; 589 *(LprimeStokes+num_dof*numgrids2d*3+num_dof*i+1)=l1l2l3[i]; 590 *(LprimeStokes+num_dof*numgrids2d*3+num_dof*i+2)=0; 591 *(LprimeStokes+num_dof*numgrids2d*3+num_dof*i+3)=0; 592 *(LprimeStokes+num_dof*numgrids2d*4+num_dof*i)=0; 593 *(LprimeStokes+num_dof*numgrids2d*4+num_dof*i+1)=0; 594 *(LprimeStokes+num_dof*numgrids2d*4+num_dof*i+2)=l1l2l3[i]; 595 *(LprimeStokes+num_dof*numgrids2d*4+num_dof*i+3)=0; 596 *(LprimeStokes+num_dof*numgrids2d*5+num_dof*i)=0; 597 *(LprimeStokes+num_dof*numgrids2d*5+num_dof*i+1)=0; 598 *(LprimeStokes+num_dof*numgrids2d*5+num_dof*i+2)=l1l2l3[i]; 599 *(LprimeStokes+num_dof*numgrids2d*5+num_dof*i+3)=0; 600 *(LprimeStokes+num_dof*numgrids2d*6+num_dof*i)=0; 601 *(LprimeStokes+num_dof*numgrids2d*6+num_dof*i+1)=0; 602 *(LprimeStokes+num_dof*numgrids2d*6+num_dof*i+2)=dh1dh6[2][i]; 603 *(LprimeStokes+num_dof*numgrids2d*6+num_dof*i+3)=0; 604 *(LprimeStokes+num_dof*numgrids2d*7+num_dof*i)=0; 605 *(LprimeStokes+num_dof*numgrids2d*7+num_dof*i+1)=0; 606 *(LprimeStokes+num_dof*numgrids2d*7+num_dof*i+2)=dh1dh6[2][i]; 607 *(LprimeStokes+num_dof*numgrids2d*7+num_dof*i+3)=0; 608 *(LprimeStokes+num_dof*numgrids2d*8+num_dof*i)=0; 609 *(LprimeStokes+num_dof*numgrids2d*8+num_dof*i+1)=0; 610 *(LprimeStokes+num_dof*numgrids2d*8+num_dof*i+2)=dh1dh6[2][i]; 611 *(LprimeStokes+num_dof*numgrids2d*8+num_dof*i+3)=0; 612 *(LprimeStokes+num_dof*numgrids2d*9+num_dof*i)=dh1dh6[2][i]; 613 *(LprimeStokes+num_dof*numgrids2d*9+num_dof*i+1)=0; 614 *(LprimeStokes+num_dof*numgrids2d*9+num_dof*i+2)=dh1dh6[0][i]; 615 *(LprimeStokes+num_dof*numgrids2d*9+num_dof*i+3)=0; 616 *(LprimeStokes+num_dof*numgrids2d*10+num_dof*i)=0; 617 *(LprimeStokes+num_dof*numgrids2d*10+num_dof*i+1)=dh1dh6[2][i]; 618 *(LprimeStokes+num_dof*numgrids2d*10+num_dof*i+2)=dh1dh6[1][i]; 619 *(LprimeStokes+num_dof*numgrids2d*10+num_dof*i+3)=0; 620 *(LprimeStokes+num_dof*numgrids2d*11+num_dof*i)=0; 621 *(LprimeStokes+num_dof*numgrids2d*11+num_dof*i+1)=0; 622 *(LprimeStokes+num_dof*numgrids2d*11+num_dof*i+2)=0; 623 *(LprimeStokes+num_dof*numgrids2d*11+num_dof*i+3)=l1l2l3[i]; 624 *(LprimeStokes+num_dof*numgrids2d*12+num_dof*i)=0; 625 *(LprimeStokes+num_dof*numgrids2d*12+num_dof*i+1)=0; 626 *(LprimeStokes+num_dof*numgrids2d*12+num_dof*i+2)=0; 627 *(LprimeStokes+num_dof*numgrids2d*12+num_dof*i+3)=l1l2l3[i]; 628 *(LprimeStokes+num_dof*numgrids2d*13+num_dof*i)=0; 629 *(LprimeStokes+num_dof*numgrids2d*13+num_dof*i+1)=0; 630 *(LprimeStokes+num_dof*numgrids2d*13+num_dof*i+2)=0; 631 *(LprimeStokes+num_dof*numgrids2d*13+num_dof*i+3)=l1l2l3[i]; 632 633 } 634 } 635 /*}}}*/ 636 /*FUNCTION PentaRef::GetJacobian {{{1*/ 637 void PentaRef::GetJacobian(double* J, double* xyz_list,double* gauss){ 638 639 const int NDOF3=3; 640 int i,j; 641 642 /*The Jacobian is constant over the element, discard the gaussian points. 643 * J is assumed to have been allocated of size NDOF2xNDOF2.*/ 644 645 double A1,A2,A3; //area coordinates 646 double xi,eta,zi; //parametric coordinates 647 648 double x1,x2,x3,x4,x5,x6; 649 double y1,y2,y3,y4,y5,y6; 650 double z1,z2,z3,z4,z5,z6; 651 652 /*Figure out xi,eta and zi (parametric coordinates), for this gaussian point: */ 653 A1=gauss[0]; 654 A2=gauss[1]; 655 A3=gauss[2]; 656 657 xi=A2-A1; 658 eta=SQRT3*A3; 659 zi=gauss[3]; 660 661 x1=*(xyz_list+3*0+0); 662 x2=*(xyz_list+3*1+0); 663 x3=*(xyz_list+3*2+0); 664 x4=*(xyz_list+3*3+0); 665 x5=*(xyz_list+3*4+0); 666 x6=*(xyz_list+3*5+0); 667 668 y1=*(xyz_list+3*0+1); 669 y2=*(xyz_list+3*1+1); 670 y3=*(xyz_list+3*2+1); 671 y4=*(xyz_list+3*3+1); 672 y5=*(xyz_list+3*4+1); 673 y6=*(xyz_list+3*5+1); 674 675 z1=*(xyz_list+3*0+2); 676 z2=*(xyz_list+3*1+2); 677 z3=*(xyz_list+3*2+2); 678 z4=*(xyz_list+3*3+2); 679 z5=*(xyz_list+3*4+2); 680 z6=*(xyz_list+3*5+2); 681 682 *(J+NDOF3*0+0)=0.25*(x1-x2-x4+x5)*zi+0.25*(-x1+x2-x4+x5); 683 *(J+NDOF3*1+0)=SQRT3/12.0*(x1+x2-2*x3-x4-x5+2*x6)*zi+SQRT3/12.0*(-x1-x2+2*x3-x4-x5+2*x6); 684 *(J+NDOF3*2+0)=SQRT3/12.0*(x1+x2-2*x3-x4-x5+2*x6)*eta+1/4*(x1-x2-x4+x5)*xi +0.25*(-x1+x5-x2+x4); 685 686 *(J+NDOF3*0+1)=0.25*(y1-y2-y4+y5)*zi+0.25*(-y1+y2-y4+y5); 687 *(J+NDOF3*1+1)=SQRT3/12.0*(y1+y2-2*y3-y4-y5+2*y6)*zi+SQRT3/12.0*(-y1-y2+2*y3-y4-y5+2*y6); 688 *(J+NDOF3*2+1)=SQRT3/12.0*(y1+y2-2*y3-y4-y5+2*y6)*eta+0.25*(y1-y2-y4+y5)*xi+0.25*(y4-y1+y5-y2); 689 690 *(J+NDOF3*0+2)=0.25*(z1-z2-z4+z5)*zi+0.25*(-z1+z2-z4+z5); 691 *(J+NDOF3*1+2)=SQRT3/12.0*(z1+z2-2*z3-z4-z5+2*z6)*zi+SQRT3/12.0*(-z1-z2+2*z3-z4-z5+2*z6); 692 *(J+NDOF3*2+2)=SQRT3/12.0*(z1+z2-2*z3-z4-z5+2*z6)*eta+0.25*(z1-z2-z4+z5)*xi+0.25*(-z1+z5-z2+z4); 693 694 } 695 /*}}}*/ 696 /*FUNCTION PentaRef::GetJacobianDeterminant {{{1*/ 697 void PentaRef::GetJacobianDeterminant(double* Jdet, double* xyz_list,double* gauss){ 698 /*On a penta, Jacobian varies according to coordinates. We need to get the Jacobian, and take 699 * the determinant of it: */ 700 const int NDOF3=3; 701 double J[NDOF3][NDOF3]; 702 703 GetJacobian(&J[0][0],xyz_list,gauss); 704 705 *Jdet= J[0][0]*J[1][1]*J[2][2]-J[0][0]*J[1][2]*J[2][1]-J[1][0]*J[0][1]*J[2][2]+J[1][0]*J[0][2]*J[2][1]+J[2][0]*J[0][1]*J[1][2]-J[2][0]*J[0][2]*J[1][1]; 706 707 if(*Jdet<0){ 708 ISSMERROR("negative jacobian determinant!"); 709 } 710 } 711 /*}}}*/ 712 /*FUNCTION PentaRef::GetJacobianInvert {{{1*/ 713 void PentaRef::GetJacobianInvert(double* Jinv, double* xyz_list,double* gauss){ 714 715 double Jdet; 716 const int NDOF3=3; 717 718 /*Call Jacobian routine to get the jacobian:*/ 719 GetJacobian(Jinv, xyz_list, gauss); 720 721 /*Invert Jacobian matrix: */ 722 MatrixInverse(Jinv,NDOF3,NDOF3,NULL,0,&Jdet); 723 } 724 /*}}}*/ 725 /*FUNCTION PentaRef::GetNodalFunctionsMINI{{{1*/ 726 void PentaRef::GetNodalFunctionsMINI(double* l1l7, double* gauss){ 727 /*This routine returns the values of the nodal functions at the gaussian point.*/ 728 729 l1l7[0]=gauss[0]*(1.0-gauss[3])/2.0; 730 l1l7[1]=gauss[1]*(1.0-gauss[3])/2.0; 731 l1l7[2]=gauss[2]*(1.0-gauss[3])/2.0; 732 l1l7[3]=gauss[0]*(1.0+gauss[3])/2.0; 733 l1l7[4]=gauss[1]*(1.0+gauss[3])/2.0; 734 l1l7[5]=gauss[2]*(1.0+gauss[3])/2.0; 735 l1l7[6]=27*gauss[0]*gauss[1]*gauss[2]*(1.0+gauss[3])*(1.0-gauss[3]); 736 737 } 738 /*}}}*/ 739 /*FUNCTION PentaRef::GetNodalFunctionsMINIDerivatives{{{1*/ 740 void PentaRef::GetNodalFunctionsMINIDerivatives(double* dh1dh7,double* xyz_list, double* gauss){ 741 742 /*This routine returns the values of the nodal functions derivatives (with respect to the 743 * actual coordinate system): */ 744 745 int i; 746 const int numgrids = 7; 747 double dh1dh7_ref[3][numgrids]; 748 double Jinv[3][3]; 749 750 /*Get derivative values with respect to parametric coordinate system: */ 751 GetNodalFunctionsMINIDerivativesReference(&dh1dh7_ref[0][0], gauss); 752 753 /*Get Jacobian invert: */ 754 GetJacobianInvert(&Jinv[0][0], xyz_list, gauss); 755 756 /*Build dh1dh6: 757 * 758 * [dhi/dx]= Jinv'*[dhi/dr] 759 * [dhi/dy] [dhi/ds] 760 * [dhi/dz] [dhi/dzeta] 761 */ 762 763 for (i=0;i<numgrids;i++){ 764 *(dh1dh7+numgrids*0+i)=Jinv[0][0]*dh1dh7_ref[0][i]+Jinv[0][1]*dh1dh7_ref[1][i]+Jinv[0][2]*dh1dh7_ref[2][i]; 765 *(dh1dh7+numgrids*1+i)=Jinv[1][0]*dh1dh7_ref[0][i]+Jinv[1][1]*dh1dh7_ref[1][i]+Jinv[1][2]*dh1dh7_ref[2][i]; 766 *(dh1dh7+numgrids*2+i)=Jinv[2][0]*dh1dh7_ref[0][i]+Jinv[2][1]*dh1dh7_ref[1][i]+Jinv[2][2]*dh1dh7_ref[2][i]; 767 } 768 769 } 770 /*}}}*/ 771 /*FUNCTION PentaRef::GetNodalFunctionsMINIDerivativesReference{{{1*/ 772 void PentaRef::GetNodalFunctionsMINIDerivativesReference(double* dl1dl7,double* gauss){ 773 774 /*This routine returns the values of the nodal functions derivatives (with respect to the 775 * natural coordinate system) at the gaussian point. */ 776 777 int numgrids=7; //six plus bubble grids 778 779 double r=gauss[1]-gauss[0]; 780 double s=-3.0/SQRT3*(gauss[0]+gauss[1]-2.0/3.0); 781 double zeta=gauss[3]; 782 783 /*First nodal function: */ 784 *(dl1dl7+numgrids*0+0)=-0.5*(1.0-zeta)/2.0; 785 *(dl1dl7+numgrids*1+0)=-SQRT3/6.0*(1.0-zeta)/2.0; 786 *(dl1dl7+numgrids*2+0)=-0.5*(-0.5*r-SQRT3/6.0*s+ONETHIRD); 787 788 /*Second nodal function: */ 789 *(dl1dl7+numgrids*0+1)=0.5*(1.0-zeta)/2.0; 790 *(dl1dl7+numgrids*1+1)=-SQRT3/6.0*(1.0-zeta)/2.0; 791 *(dl1dl7+numgrids*2+1)=-0.5*(0.5*r-SQRT3/6.0*s+ONETHIRD); 792 793 /*Third nodal function: */ 794 *(dl1dl7+numgrids*0+2)=0; 795 *(dl1dl7+numgrids*1+2)=SQRT3/3.0*(1.0-zeta)/2.0; 796 *(dl1dl7+numgrids*2+2)=-0.5*(SQRT3/3.0*s+ONETHIRD); 797 798 /*Fourth nodal function: */ 799 *(dl1dl7+numgrids*0+3)=-0.5*(1.0+zeta)/2.0; 800 *(dl1dl7+numgrids*1+3)=-SQRT3/6.0*(1.0+zeta)/2.0; 801 *(dl1dl7+numgrids*2+3)=0.5*(-0.5*r-SQRT3/6.0*s+ONETHIRD); 802 803 /*Fith nodal function: */ 804 *(dl1dl7+numgrids*0+4)=0.5*(1.0+zeta)/2.0; 805 *(dl1dl7+numgrids*1+4)=-SQRT3/6.0*(1.0+zeta)/2.0; 806 *(dl1dl7+numgrids*2+4)=0.5*(0.5*r-SQRT3/6.0*s+ONETHIRD); 807 808 /*Sixth nodal function: */ 809 *(dl1dl7+numgrids*0+5)=0; 810 *(dl1dl7+numgrids*1+5)=SQRT3/3.0*(1.0+zeta)/2.0; 811 *(dl1dl7+numgrids*2+5)=0.5*(SQRT3/3.0*s+ONETHIRD); 812 813 /*Seventh nodal function: */ 814 *(dl1dl7+numgrids*0+6)=9.0/2.0*r*(1.0+zeta)*(zeta-1.0)*(SQRT3*s+1.0); 815 *(dl1dl7+numgrids*1+6)=9.0/4.0*(1+zeta)*(1-zeta)*(SQRT3*pow(s,2.0)-2.0*s-SQRT3*pow(r,2.0)); 816 *(dl1dl7+numgrids*2+6)=27*gauss[0]*gauss[1]*gauss[2]*(-2.0*zeta); 817 818 } 819 /*}}}*/ 820 /*FUNCTION PentaRef::GetNodalFunctionsP1 {{{1*/ 821 void PentaRef::GetNodalFunctionsP1(double* l1l6, double* gauss){ 822 /*This routine returns the values of the nodal functions at the gaussian point.*/ 823 824 l1l6[0]=gauss[0]*(1-gauss[3])/2.0; 825 l1l6[1]=gauss[1]*(1-gauss[3])/2.0; 826 l1l6[2]=gauss[2]*(1-gauss[3])/2.0; 827 l1l6[3]=gauss[0]*(1+gauss[3])/2.0; 828 l1l6[4]=gauss[1]*(1+gauss[3])/2.0; 829 l1l6[5]=gauss[2]*(1+gauss[3])/2.0; 830 831 } 832 /*}}}*/ 833 /*FUNCTION PentaRef::GetNodalFunctionsP1Derivatives {{{1*/ 834 void PentaRef::GetNodalFunctionsP1Derivatives(double* dh1dh6,double* xyz_list, double* gauss){ 835 836 /*This routine returns the values of the nodal functions derivatives (with respect to the 837 * actual coordinate system): */ 838 int i; 839 const int NDOF3 = 3; 840 const int numgrids = 6; 841 double dh1dh6_ref[NDOF3][numgrids]; 842 double Jinv[NDOF3][NDOF3]; 843 844 /*Get derivative values with respect to parametric coordinate system: */ 845 GetNodalFunctionsP1DerivativesReference(&dh1dh6_ref[0][0], gauss); 846 847 /*Get Jacobian invert: */ 848 GetJacobianInvert(&Jinv[0][0], xyz_list, gauss); 849 850 /*Build dh1dh3: 851 * 852 * [dhi/dx]= Jinv*[dhi/dr] 853 * [dhi/dy] [dhi/ds] 854 * [dhi/dz] [dhi/dn] 855 */ 856 857 for (i=0;i<numgrids;i++){ 858 *(dh1dh6+numgrids*0+i)=Jinv[0][0]*dh1dh6_ref[0][i]+Jinv[0][1]*dh1dh6_ref[1][i]+Jinv[0][2]*dh1dh6_ref[2][i]; 859 *(dh1dh6+numgrids*1+i)=Jinv[1][0]*dh1dh6_ref[0][i]+Jinv[1][1]*dh1dh6_ref[1][i]+Jinv[1][2]*dh1dh6_ref[2][i]; 860 *(dh1dh6+numgrids*2+i)=Jinv[2][0]*dh1dh6_ref[0][i]+Jinv[2][1]*dh1dh6_ref[1][i]+Jinv[2][2]*dh1dh6_ref[2][i]; 861 } 862 863 } 864 /*}}}*/ 865 /*FUNCTION PentaRef::GetNodalFunctionsP1DerivativesReference {{{1*/ 866 void PentaRef::GetNodalFunctionsP1DerivativesReference(double* dl1dl6,double* gauss){ 867 868 /*This routine returns the values of the nodal functions derivatives (with respect to the 869 * natural coordinate system) at the gaussian point. Those values vary along xi,eta,z */ 870 871 const int numgrids=6; 872 double A1,A2,A3,z; 873 874 A1=gauss[0]; //first area coordinate value. In term of xi and eta: A1=(1-xi)/2-eta/(2*SQRT3); 875 A2=gauss[1]; //second area coordinate value In term of xi and eta: A2=(1+xi)/2-eta/(2*SQRT3); 876 A3=gauss[2]; //third area coordinate value In term of xi and eta: A3=y/SQRT3; 877 z=gauss[3]; //fourth vertical coordinate value. Corresponding nodal function: (1-z)/2 and (1+z)/2 878 879 880 /*First nodal function derivatives. The corresponding nodal function is N=A1*(1-z)/2. Its derivatives follow*/ 881 *(dl1dl6+numgrids*0+0)=-0.5*(1.0-z)/2.0; 882 *(dl1dl6+numgrids*1+0)=-0.5/SQRT3*(1.0-z)/2.0; 883 *(dl1dl6+numgrids*2+0)=-0.5*A1; 884 885 /*Second nodal function: The corresponding nodal function is N=A2*(1-z)/2. Its derivatives follow*/ 886 *(dl1dl6+numgrids*0+1)=0.5*(1.0-z)/2.0; 887 *(dl1dl6+numgrids*1+1)=-0.5/SQRT3*(1.0-z)/2.0; 888 *(dl1dl6+numgrids*2+1)=-0.5*A2; 889 890 /*Third nodal function: The corresponding nodal function is N=A3*(1-z)/2. Its derivatives follow*/ 891 *(dl1dl6+numgrids*0+2)=0.0; 892 *(dl1dl6+numgrids*1+2)=1.0/SQRT3*(1.0-z)/2.0; 893 *(dl1dl6+numgrids*2+2)=-0.5*A3; 894 895 /*Fourth nodal function: The corresponding nodal function is N=A1*(1+z)/2. Its derivatives follow*/ 896 *(dl1dl6+numgrids*0+3)=-0.5*(1.0+z)/2.0; 897 *(dl1dl6+numgrids*1+3)=-0.5/SQRT3*(1.0+z)/2.0; 898 *(dl1dl6+numgrids*2+3)=0.5*A1; 899 900 /*Fifth nodal function: The corresponding nodal function is N=A2*(1+z)/2. Its derivatives follow*/ 901 *(dl1dl6+numgrids*0+4)=0.5*(1.0+z)/2.0; 902 *(dl1dl6+numgrids*1+4)=-0.5/SQRT3*(1.0+z)/2.0; 903 *(dl1dl6+numgrids*2+4)=0.5*A2; 904 905 /*Sixth nodal function: The corresponding nodal function is N=A3*(1+z)/2. Its derivatives follow*/ 906 *(dl1dl6+numgrids*0+5)=0.0; 907 *(dl1dl6+numgrids*1+5)=1.0/SQRT3*(1.0+z)/2.0; 908 *(dl1dl6+numgrids*2+5)=0.5*A3; 909 } 910 /*}}}*/ -
issm/trunk/src/c/objects/Elements/PentaRef.h
r4882 r4885 23 23 24 24 /*Numerics*/ 25 void GetNodalFunctionsP1(double* l1l6, double* gauss); 26 void GetNodalFunctionsMINI(double* l1l7, double* gauss); 27 void GetNodalFunctionsP1Derivatives(double* dh1dh6,double* xyz_list, double* gauss); 28 void GetNodalFunctionsMINIDerivatives(double* dh1dh7,double* xyz_list, double* gauss); 29 void GetNodalFunctionsP1DerivativesReference(double* dl1dl6,double* gauss); 30 void GetNodalFunctionsMINIDerivativesReference(double* dl1dl7,double* gauss); 31 void GetJacobian(double* J, double* xyz_list,double* gauss); 32 void GetJacobianDeterminant(double* Jdet, double* xyz_list,double* gauss); 33 void GetJacobianInvert(double* Jinv, double* xyz_list,double* gauss); 34 void GetBPattyn(double* B, double* xyz_list, double* gauss); 35 void GetBprimePattyn(double* B, double* xyz_list, double* gauss); 36 void GetBStokes(double* B, double* xyz_list, double* gauss); 37 void GetBprimeStokes(double* B_prime, double* xyz_list, double* gauss); 38 void GetBprimeVert(double* B, double* xyz_list, double* gauss); 39 void GetBAdvec(double* B_advec, double* xyz_list, double* gauss); 40 void GetBArtdiff(double* B_artdiff, double* xyz_list, double* gauss); 41 void GetBConduct(double* B_conduct, double* xyz_list, double* gauss); 42 void GetBVert(double* B, double* xyz_list, double* gauss); 43 void GetBprimeAdvec(double* Bprime_advec, double* xyz_list, double* gauss); 44 void GetLStokes(double* LStokes, double* gauss_tria); 45 void GetLprimeStokes(double* LprimeStokes, double* xyz_list, double* gauss_tria, double* gauss); 25 46 26 47 }; -
issm/trunk/src/c/objects/Elements/Tria.cpp
r4882 r4885 146 146 int i; 147 147 int flaghook; 148 int type;149 148 150 149 /*recover marshalled_dataset: */ … … 158 157 /*demarshall Ref: */ 159 158 this->element_type_list=(int*)xmalloc(this->numanalyses*sizeof(int)); 160 for(i=0;i<numanalyses;i++){ memcpy(&element_type_list[i],marshalled_dataset,sizeof( type));marshalled_dataset+=sizeof(type);}159 for(i=0;i<numanalyses;i++){ memcpy(&element_type_list[i],marshalled_dataset,sizeof(int));marshalled_dataset+=sizeof(int);} 161 160 162 161 /*allocate dynamic memory: */ … … 2373 2372 2374 2373 /*Get B and B prime matrix: */ 2375 GetB _prog(&B[0][0], &xyz_list[0][0], gauss_l1l2l3);2376 GetB Prime_prog(&Bprime[0][0], &xyz_list[0][0], gauss_l1l2l3);2374 GetBPrognostic(&B[0][0], &xyz_list[0][0], gauss_l1l2l3); 2375 GetBprimePrognostic(&Bprime[0][0], &xyz_list[0][0], gauss_l1l2l3); 2377 2376 2378 2377 //Get vx, vy and their derivatives at gauss point … … 2506 2505 /*Get B and B prime matrix: */ 2507 2506 /*WARNING: B and Bprime are inverted compared to usual prognostic!!!!*/ 2508 GetB _prog(&Bprime[0][0], &xyz_list[0][0], gauss_l1l2l3);2509 GetB Prime_prog(&B[0][0], &xyz_list[0][0], gauss_l1l2l3);2507 GetBPrognostic(&Bprime[0][0], &xyz_list[0][0], gauss_l1l2l3); 2508 GetBprimePrognostic(&B[0][0], &xyz_list[0][0], gauss_l1l2l3); 2510 2509 2511 2510 //Get vx, vy and their derivatives at gauss point … … 2656 2655 2657 2656 /*Get B and B prime matrix: */ 2658 GetB _prog(&B[0][0], &xyz_list[0][0], gauss_l1l2l3);2659 GetB Prime_prog(&Bprime[0][0], &xyz_list[0][0], gauss_l1l2l3);2657 GetBPrognostic(&B[0][0], &xyz_list[0][0], gauss_l1l2l3); 2658 GetBprimePrognostic(&Bprime[0][0], &xyz_list[0][0], gauss_l1l2l3); 2660 2659 2661 2660 //Get vx, vy and their derivatives at gauss point … … 2829 2828 2830 2829 /*Get B and Bprime matrices: */ 2831 GetB (&B[0][0], &xyz_list[0][0], gauss_l1l2l3);2832 GetB Prime(&Bprime[0][0], &xyz_list[0][0], gauss_l1l2l3);2830 GetBMacAyeal(&B[0][0], &xyz_list[0][0], gauss_l1l2l3); 2831 GetBprimeMacAyeal(&Bprime[0][0], &xyz_list[0][0], gauss_l1l2l3); 2833 2832 2834 2833 /* Do the triple product tB*D*Bprime: */ … … 3338 3337 3339 3338 /*Get B and B prime matrix: */ 3340 GetB _prog(&B[0][0], &xyz_list[0][0], gauss_l1l2l3);3341 GetB Prime_prog(&Bprime[0][0], &xyz_list[0][0], gauss_l1l2l3);3339 GetBPrognostic(&B[0][0], &xyz_list[0][0], gauss_l1l2l3); 3340 GetBprimePrognostic(&Bprime[0][0], &xyz_list[0][0], gauss_l1l2l3); 3342 3341 3343 3342 //Get vx, vy and their derivatives at gauss point … … 3492 3491 /*Get B and B prime matrix: */ 3493 3492 /*WARNING: B and Bprime are inverted compared to usual prognostic!!!!*/ 3494 GetB _prog(&Bprime[0][0], &xyz_list[0][0], gauss_l1l2l3);3495 GetB Prime_prog(&B[0][0], &xyz_list[0][0], gauss_l1l2l3);3493 GetBPrognostic(&Bprime[0][0], &xyz_list[0][0], gauss_l1l2l3); 3494 GetBprimePrognostic(&B[0][0], &xyz_list[0][0], gauss_l1l2l3); 3496 3495 3497 3496 //Get vx, vy and their derivatives at gauss point -
issm/trunk/src/c/objects/Elements/TriaRef.cpp
r4770 r4885 52 52 53 53 /*Reference Element numerics*/ 54 /*FUNCTION TriaRef::GetB {{{1*/55 void TriaRef::GetB (double* B, double* xyz_list, double* gauss){54 /*FUNCTION TriaRef::GetBMacAyeal {{{1*/ 55 void TriaRef::GetBMacAyeal(double* B, double* xyz_list, double* gauss){ 56 56 /*Compute B matrix. B=[B1 B2 B3] where Bi is of size 3*NDOF2. 57 57 * For grid i, Bi can be expressed in the actual coordinate system … … 86 86 } 87 87 /*}}}*/ 88 /*FUNCTION TriaRef::GetB _prog{{{1*/89 void TriaRef::GetB _prog(double* B_prog, double* xyz_list, double* gauss){88 /*FUNCTION TriaRef::GetBPrognostic{{{1*/ 89 void TriaRef::GetBPrognostic(double* B_prog, double* xyz_list, double* gauss){ 90 90 /*Compute B matrix. B=[B1 B2 B3] where Bi is of size 3*NDOF2. 91 91 * For grid i, Bi can be expressed in the actual coordinate system … … 115 115 } 116 116 /*}}}*/ 117 /*FUNCTION TriaRef::GetB Prime{{{1*/118 void TriaRef::GetB Prime(double* Bprime, double* xyz_list, double* gauss){117 /*FUNCTION TriaRef::GetBprimeMacAyeal {{{1*/ 118 void TriaRef::GetBprimeMacAyeal(double* Bprime, double* xyz_list, double* gauss){ 119 119 120 120 /*Compute B' matrix. B'=[B1' B2' B3'] where Bi' is of size 3*NDOF2. … … 150 150 } 151 151 /*}}}*/ 152 /*FUNCTION TriaRef::GetB Prime_prog{{{1*/153 void TriaRef::GetB Prime_prog(double* Bprime_prog, double* xyz_list, double* gauss){152 /*FUNCTION TriaRef::GetBprimePrognostic{{{1*/ 153 void TriaRef::GetBprimePrognostic(double* Bprime_prog, double* xyz_list, double* gauss){ 154 154 /*Compute B' matrix. B'=[B1' B2' B3'] where Bi' is of size 3*NDOF2. 155 155 * For grid i, Bi' can be expressed in the actual coordinate system 156 156 * by: 157 157 * Bi_prime=[ dh/dx ] 158 * 158 * [ dh/dy ] 159 159 * where h is the interpolation function for grid i. 160 160 * … … 186 186 * by: 187 187 * numdof=1: 188 * Li=h;188 * Li=h; 189 189 * numdof=2: 190 * Li=[ h 0]191 * [ 0 h]190 * Li=[ h 0 ] 191 * [ 0 h ] 192 192 * where h is the interpolation function for grid i. 193 193 * … … 310 310 /*FUNCTION TriaRef::GetNodalFunctions {{{1*/ 311 311 void TriaRef::GetNodalFunctions(double* l1l2l3, double* gauss){ 312 313 312 /*This routine returns the values of the nodal functions at the gaussian point.*/ 314 313 315 /*First nodal function: */316 314 l1l2l3[0]=gauss[0]; 317 318 /*Second nodal function: */319 315 l1l2l3[1]=gauss[1]; 320 321 /*Third nodal function: */322 316 l1l2l3[2]=gauss[2]; 323 317 … … 328 322 329 323 /*This routine returns the values of the nodal functions derivatives (with respect to the 330 * actual coordinate system : */331 int i;332 const int NDOF2 =2;333 const int numgrids =3;334 double dh1dh3_ref[NDOF2][numgrids];335 double Jinv[NDOF2][NDOF2];324 * actual coordinate system): */ 325 int i; 326 const int NDOF2 = 2; 327 const int numgrids = 3; 328 double dh1dh3_ref[NDOF2][numgrids]; 329 double Jinv[NDOF2][NDOF2]; 336 330 337 331 /*Get derivative values with respect to parametric coordinate system: */ -
issm/trunk/src/c/objects/Elements/TriaRef.h
r4770 r4885 23 23 24 24 /*Numerics*/ 25 void GetB (double* B, double* xyz_list, double* gauss);26 void GetB Prime(double* Bprime, double* xyz_list, double* gauss);27 void GetB Prime_prog(double* Bprime_prog, double* xyz_list, double* gauss);28 void GetB _prog(double* B_prog, double* xyz_list, double* gauss);25 void GetBMacAyeal(double* B, double* xyz_list, double* gauss); 26 void GetBprimeMacAyeal(double* Bprime, double* xyz_list, double* gauss); 27 void GetBprimePrognostic(double* Bprime_prog, double* xyz_list, double* gauss); 28 void GetBPrognostic(double* B_prog, double* xyz_list, double* gauss); 29 29 void GetL(double* L, double* xyz_list, double* gauss,int numdof); 30 30 void GetJacobian(double* J, double* xyz_list,double* gauss); -
issm/trunk/src/c/objects/Inputs/PentaVertexInput.cpp
r4882 r4885 481 481 482 482 /*Intermediary*/ 483 /*FUNCTION PentaVertexInput::GetNodalFunctionsP1 {{{1*/484 void PentaVertexInput::GetNodalFunctionsP1(double* l1l6, double* gauss_coord){485 486 /*This routine returns the values of the nodal functions at the gaussian point.*/487 488 l1l6[0]=gauss_coord[0]*(1-gauss_coord[3])/2.0;489 490 l1l6[1]=gauss_coord[1]*(1-gauss_coord[3])/2.0;491 492 l1l6[2]=gauss_coord[2]*(1-gauss_coord[3])/2.0;493 494 l1l6[3]=gauss_coord[0]*(1+gauss_coord[3])/2.0;495 496 l1l6[4]=gauss_coord[1]*(1+gauss_coord[3])/2.0;497 498 l1l6[5]=gauss_coord[2]*(1+gauss_coord[3])/2.0;499 500 }501 /*}}}*/502 /*FUNCTION PentaVertexInput::GetNodalFunctionsMINI{{{1*/503 void PentaVertexInput::GetNodalFunctionsMINI(double* l1l7, double* gauss_coord){504 505 /*This routine returns the values of the nodal functions at the gaussian point.*/506 507 /*First nodal function: */508 l1l7[0]=gauss_coord[0]*(1.0-gauss_coord[3])/2.0;509 510 /*Second nodal function: */511 l1l7[1]=gauss_coord[1]*(1.0-gauss_coord[3])/2.0;512 513 /*Third nodal function: */514 l1l7[2]=gauss_coord[2]*(1.0-gauss_coord[3])/2.0;515 516 /*Fourth nodal function: */517 l1l7[3]=gauss_coord[0]*(1.0+gauss_coord[3])/2.0;518 519 /*Fifth nodal function: */520 l1l7[4]=gauss_coord[1]*(1.0+gauss_coord[3])/2.0;521 522 /*Sixth nodal function: */523 l1l7[5]=gauss_coord[2]*(1.0+gauss_coord[3])/2.0;524 525 /*Seventh nodal function: */526 l1l7[6]=27*gauss_coord[0]*gauss_coord[1]*gauss_coord[2]*(1.0+gauss_coord[3])*(1.0-gauss_coord[3]);527 528 }529 /*}}}*/530 /*FUNCTION PentaVertexInput::GetNodalFunctionsP1Derivatives {{{1*/531 void PentaVertexInput::GetNodalFunctionsP1Derivatives(double* dh1dh6,double* xyz_list, double* gauss_coord){532 533 /*This routine returns the values of the nodal functions derivatives (with respect to the actual coordinate system: */534 int i;535 const int NDOF3=3;536 const int numgrids=6;537 538 double dh1dh6_ref[NDOF3][numgrids];539 double Jinv[NDOF3][NDOF3];540 541 /*Get derivative values with respect to parametric coordinate system: */542 GetNodalFunctionsP1DerivativesReference(&dh1dh6_ref[0][0], gauss_coord);543 544 /*Get Jacobian invert: */545 GetJacobianInvert(&Jinv[0][0], xyz_list, gauss_coord);546 547 /*Build dh1dh3:548 *549 * [dhi/dx]= Jinv*[dhi/dr]550 * [dhi/dy] [dhi/ds]551 * [dhi/dz] [dhi/dn]552 */553 554 for (i=0;i<numgrids;i++){555 *(dh1dh6+numgrids*0+i)=Jinv[0][0]*dh1dh6_ref[0][i]+Jinv[0][1]*dh1dh6_ref[1][i]+Jinv[0][2]*dh1dh6_ref[2][i];556 *(dh1dh6+numgrids*1+i)=Jinv[1][0]*dh1dh6_ref[0][i]+Jinv[1][1]*dh1dh6_ref[1][i]+Jinv[1][2]*dh1dh6_ref[2][i];557 *(dh1dh6+numgrids*2+i)=Jinv[2][0]*dh1dh6_ref[0][i]+Jinv[2][1]*dh1dh6_ref[1][i]+Jinv[2][2]*dh1dh6_ref[2][i];558 }559 560 }561 /*}}}*/562 /*FUNCTION PentaVertexInput::GetNodalFunctionsMINIDerivatives{{{1*/563 void PentaVertexInput::GetNodalFunctionsMINIDerivatives(double* dh1dh7,double* xyz_list, double* gauss_coord){564 565 /*This routine returns the values of the nodal functions derivatives (with respect to the566 * actual coordinate system: */567 568 int i;569 570 const int numgrids=7;571 double dh1dh7_ref[3][numgrids];572 double Jinv[3][3];573 574 575 /*Get derivative values with respect to parametric coordinate system: */576 GetNodalFunctionsMINIDerivativesReference(&dh1dh7_ref[0][0], gauss_coord);577 578 /*Get Jacobian invert: */579 GetJacobianInvert(&Jinv[0][0], xyz_list, gauss_coord);580 581 /*Build dh1dh6:582 *583 * [dhi/dx]= Jinv'*[dhi/dr]584 * [dhi/dy] [dhi/ds]585 * [dhi/dz] [dhi/dzeta]586 */587 588 for (i=0;i<numgrids;i++){589 *(dh1dh7+numgrids*0+i)=Jinv[0][0]*dh1dh7_ref[0][i]+Jinv[0][1]*dh1dh7_ref[1][i]+Jinv[0][2]*dh1dh7_ref[2][i];590 *(dh1dh7+numgrids*1+i)=Jinv[1][0]*dh1dh7_ref[0][i]+Jinv[1][1]*dh1dh7_ref[1][i]+Jinv[1][2]*dh1dh7_ref[2][i];591 *(dh1dh7+numgrids*2+i)=Jinv[2][0]*dh1dh7_ref[0][i]+Jinv[2][1]*dh1dh7_ref[1][i]+Jinv[2][2]*dh1dh7_ref[2][i];592 }593 594 }595 /*}}}*/596 /*FUNCTION PentaVertexInput::GetNodalFunctionsP1DerivativesReference {{{1*/597 void PentaVertexInput::GetNodalFunctionsP1DerivativesReference(double* dl1dl6,double* gauss_coord){598 599 /*This routine returns the values of the nodal functions derivatives (with respect to the600 * natural coordinate system) at the gaussian point. Those values vary along xi,eta,z */601 602 const int numgrids=6;603 double A1,A2,A3,z;604 605 A1=gauss_coord[0]; //first area coordinate value. In term of xi and eta: A1=(1-xi)/2-eta/(2*SQRT3);606 A2=gauss_coord[1]; //second area coordinate value In term of xi and eta: A2=(1+xi)/2-eta/(2*SQRT3);607 A3=gauss_coord[2]; //third area coordinate value In term of xi and eta: A3=y/SQRT3;608 z=gauss_coord[3]; //fourth vertical coordinate value. Corresponding nodal function: (1-z)/2 and (1+z)/2609 610 611 /*First nodal function derivatives. The corresponding nodal function is N=A1*(1-z)/2. Its derivatives follow*/612 *(dl1dl6+numgrids*0+0)=-0.5*(1.0-z)/2.0;613 *(dl1dl6+numgrids*1+0)=-0.5/SQRT3*(1.0-z)/2.0;614 *(dl1dl6+numgrids*2+0)=-0.5*A1;615 616 /*Second nodal function: The corresponding nodal function is N=A2*(1-z)/2. Its derivatives follow*/617 *(dl1dl6+numgrids*0+1)=0.5*(1.0-z)/2.0;618 *(dl1dl6+numgrids*1+1)=-0.5/SQRT3*(1.0-z)/2.0;619 *(dl1dl6+numgrids*2+1)=-0.5*A2;620 621 /*Third nodal function: The corresponding nodal function is N=A3*(1-z)/2. Its derivatives follow*/622 *(dl1dl6+numgrids*0+2)=0.0;623 *(dl1dl6+numgrids*1+2)=1.0/SQRT3*(1.0-z)/2.0;624 *(dl1dl6+numgrids*2+2)=-0.5*A3;625 626 /*Fourth nodal function: The corresponding nodal function is N=A1*(1+z)/2. Its derivatives follow*/627 *(dl1dl6+numgrids*0+3)=-0.5*(1.0+z)/2.0;628 *(dl1dl6+numgrids*1+3)=-0.5/SQRT3*(1.0+z)/2.0;629 *(dl1dl6+numgrids*2+3)=0.5*A1;630 631 /*Fifth nodal function: The corresponding nodal function is N=A2*(1+z)/2. Its derivatives follow*/632 *(dl1dl6+numgrids*0+4)=0.5*(1.0+z)/2.0;633 *(dl1dl6+numgrids*1+4)=-0.5/SQRT3*(1.0+z)/2.0;634 *(dl1dl6+numgrids*2+4)=0.5*A2;635 636 /*Sixth nodal function: The corresponding nodal function is N=A3*(1+z)/2. Its derivatives follow*/637 *(dl1dl6+numgrids*0+5)=0.0;638 *(dl1dl6+numgrids*1+5)=1.0/SQRT3*(1.0+z)/2.0;639 *(dl1dl6+numgrids*2+5)=0.5*A3;640 }641 /*}}}*/642 /*FUNCTION PentaVertexInput::GetNodalFunctionsMINIDerivativesReference{{{1*/643 void PentaVertexInput::GetNodalFunctionsMINIDerivativesReference(double* dl1dl7,double* gauss_coord){644 645 /*This routine returns the values of the nodal functions derivatives (with respect to the646 * natural coordinate system) at the gaussian point. */647 648 int numgrids=7; //six plus bubble grids649 650 double r=gauss_coord[1]-gauss_coord[0];651 double s=-3.0/SQRT3*(gauss_coord[0]+gauss_coord[1]-2.0/3.0);652 double zeta=gauss_coord[3];653 654 /*First nodal function: */655 *(dl1dl7+numgrids*0+0)=-0.5*(1.0-zeta)/2.0;656 *(dl1dl7+numgrids*1+0)=-SQRT3/6.0*(1.0-zeta)/2.0;657 *(dl1dl7+numgrids*2+0)=-0.5*(-0.5*r-SQRT3/6.0*s+ONETHIRD);658 659 /*Second nodal function: */660 *(dl1dl7+numgrids*0+1)=0.5*(1.0-zeta)/2.0;661 *(dl1dl7+numgrids*1+1)=-SQRT3/6.0*(1.0-zeta)/2.0;662 *(dl1dl7+numgrids*2+1)=-0.5*(0.5*r-SQRT3/6.0*s+ONETHIRD);663 664 /*Third nodal function: */665 *(dl1dl7+numgrids*0+2)=0;666 *(dl1dl7+numgrids*1+2)=SQRT3/3.0*(1.0-zeta)/2.0;667 *(dl1dl7+numgrids*2+2)=-0.5*(SQRT3/3.0*s+ONETHIRD);668 669 /*Fourth nodal function: */670 *(dl1dl7+numgrids*0+3)=-0.5*(1.0+zeta)/2.0;671 *(dl1dl7+numgrids*1+3)=-SQRT3/6.0*(1.0+zeta)/2.0;672 *(dl1dl7+numgrids*2+3)=0.5*(-0.5*r-SQRT3/6.0*s+ONETHIRD);673 674 /*Fith nodal function: */675 *(dl1dl7+numgrids*0+4)=0.5*(1.0+zeta)/2.0;676 *(dl1dl7+numgrids*1+4)=-SQRT3/6.0*(1.0+zeta)/2.0;677 *(dl1dl7+numgrids*2+4)=0.5*(0.5*r-SQRT3/6.0*s+ONETHIRD);678 679 /*Sixth nodal function: */680 *(dl1dl7+numgrids*0+5)=0;681 *(dl1dl7+numgrids*1+5)=SQRT3/3.0*(1.0+zeta)/2.0;682 *(dl1dl7+numgrids*2+5)=0.5*(SQRT3/3.0*s+ONETHIRD);683 684 /*Seventh nodal function: */685 *(dl1dl7+numgrids*0+6)=9.0/2.0*r*(1.0+zeta)*(zeta-1.0)*(SQRT3*s+1.0);686 *(dl1dl7+numgrids*1+6)=9.0/4.0*(1+zeta)*(1-zeta)*(SQRT3*pow(s,2.0)-2.0*s-SQRT3*pow(r,2.0));687 *(dl1dl7+numgrids*2+6)=27*gauss_coord[0]*gauss_coord[1]*gauss_coord[2]*(-2.0*zeta);688 689 }690 /*}}}*/691 /*FUNCTION PentaVertexInput::GetJacobian {{{1*/692 void PentaVertexInput::GetJacobian(double* J, double* xyz_list,double* gauss_coord){693 694 const int NDOF3=3;695 int i,j;696 697 /*The Jacobian is constant over the element, discard the gaussian points.698 * J is assumed to have been allocated of size NDOF2xNDOF2.*/699 700 double A1,A2,A3; //area coordinates701 double xi,eta,zi; //parametric coordinates702 703 double x1,x2,x3,x4,x5,x6;704 double y1,y2,y3,y4,y5,y6;705 double z1,z2,z3,z4,z5,z6;706 707 /*Figure out xi,eta and zi (parametric coordinates), for this gaussian point: */708 A1=gauss_coord[0];709 A2=gauss_coord[1];710 A3=gauss_coord[2];711 712 xi=A2-A1;713 eta=SQRT3*A3;714 zi=gauss_coord[3];715 716 x1=*(xyz_list+3*0+0);717 x2=*(xyz_list+3*1+0);718 x3=*(xyz_list+3*2+0);719 x4=*(xyz_list+3*3+0);720 x5=*(xyz_list+3*4+0);721 x6=*(xyz_list+3*5+0);722 723 y1=*(xyz_list+3*0+1);724 y2=*(xyz_list+3*1+1);725 y3=*(xyz_list+3*2+1);726 y4=*(xyz_list+3*3+1);727 y5=*(xyz_list+3*4+1);728 y6=*(xyz_list+3*5+1);729 730 z1=*(xyz_list+3*0+2);731 z2=*(xyz_list+3*1+2);732 z3=*(xyz_list+3*2+2);733 z4=*(xyz_list+3*3+2);734 z5=*(xyz_list+3*4+2);735 z6=*(xyz_list+3*5+2);736 737 *(J+NDOF3*0+0)=0.25*(x1-x2-x4+x5)*zi+0.25*(-x1+x2-x4+x5);738 *(J+NDOF3*1+0)=SQRT3/12.0*(x1+x2-2*x3-x4-x5+2*x6)*zi+SQRT3/12.0*(-x1-x2+2*x3-x4-x5+2*x6);739 *(J+NDOF3*2+0)=SQRT3/12.0*(x1+x2-2*x3-x4-x5+2*x6)*eta+1/4*(x1-x2-x4+x5)*xi +0.25*(-x1+x5-x2+x4);740 741 *(J+NDOF3*0+1)=0.25*(y1-y2-y4+y5)*zi+0.25*(-y1+y2-y4+y5);742 *(J+NDOF3*1+1)=SQRT3/12.0*(y1+y2-2*y3-y4-y5+2*y6)*zi+SQRT3/12.0*(-y1-y2+2*y3-y4-y5+2*y6);743 *(J+NDOF3*2+1)=SQRT3/12.0*(y1+y2-2*y3-y4-y5+2*y6)*eta+0.25*(y1-y2-y4+y5)*xi+0.25*(y4-y1+y5-y2);744 745 *(J+NDOF3*0+2)=0.25*(z1-z2-z4+z5)*zi+0.25*(-z1+z2-z4+z5);746 *(J+NDOF3*1+2)=SQRT3/12.0*(z1+z2-2*z3-z4-z5+2*z6)*zi+SQRT3/12.0*(-z1-z2+2*z3-z4-z5+2*z6);747 *(J+NDOF3*2+2)=SQRT3/12.0*(z1+z2-2*z3-z4-z5+2*z6)*eta+0.25*(z1-z2-z4+z5)*xi+0.25*(-z1+z5-z2+z4);748 749 }750 /*}}}*/751 /*FUNCTION PentaVertexInput::GetJacobianInvert {{{1*/752 void PentaVertexInput::GetJacobianInvert(double* Jinv, double* xyz_list,double* gauss_coord){753 754 double Jdet;755 const int NDOF3=3;756 757 /*Call Jacobian routine to get the jacobian:*/758 GetJacobian(Jinv, xyz_list, gauss_coord);759 760 /*Invert Jacobian matrix: */761 MatrixInverse(Jinv,NDOF3,NDOF3,NULL,0,&Jdet);762 }763 /*}}}*/764 /*FUNCTION PentaVertexInput::GetBPattyn {{{1*/765 void PentaVertexInput::GetBPattyn(double* B, double* xyz_list, double* gauss_coord){766 /*Compute B matrix. B=[B1 B2 B3 B4 B5 B6] where Bi is of size 5*NDOF2.767 * For grid i, Bi can be expressed in the actual coordinate system768 * by:769 * Bi=[ dh/dx 0 ]770 * [ 0 dh/dy ]771 * [ 1/2*dh/dy 1/2*dh/dx ]772 * [ 1/2*dh/dz 0 ]773 * [ 0 1/2*dh/dz ]774 * where h is the interpolation function for grid i.775 *776 * We assume B has been allocated already, of size: 5x(NDOF2*numgrids)777 */778 779 int i;780 const int numgrids=6;781 const int NDOF3=3;782 const int NDOF2=2;783 784 double dh1dh6[NDOF3][numgrids];785 786 /*Get dh1dh6 in actual coordinate system: */787 GetNodalFunctionsP1Derivatives(&dh1dh6[0][0],xyz_list, gauss_coord);788 789 /*Build B: */790 for (i=0;i<numgrids;i++){791 *(B+NDOF2*numgrids*0+NDOF2*i)=dh1dh6[0][i];792 *(B+NDOF2*numgrids*0+NDOF2*i+1)=0.0;793 794 *(B+NDOF2*numgrids*1+NDOF2*i)=0.0;795 *(B+NDOF2*numgrids*1+NDOF2*i+1)=dh1dh6[1][i];796 797 *(B+NDOF2*numgrids*2+NDOF2*i)=(float).5*dh1dh6[1][i];798 *(B+NDOF2*numgrids*2+NDOF2*i+1)=(float).5*dh1dh6[0][i];799 800 *(B+NDOF2*numgrids*3+NDOF2*i)=(float).5*dh1dh6[2][i];801 *(B+NDOF2*numgrids*3+NDOF2*i+1)=0.0;802 803 *(B+NDOF2*numgrids*4+NDOF2*i)=0.0;804 *(B+NDOF2*numgrids*4+NDOF2*i+1)=(float).5*dh1dh6[2][i];805 }806 807 }808 /*}}}*/809 /*FUNCTION PentaVertexInput::GetBStokes {{{1*/810 void PentaVertexInput::GetBStokes(double* B, double* xyz_list, double* gauss_coord){811 812 /*Compute B matrix. B=[B1 B2 B3 B4 B5 B6] where Bi is of size 3*DOFPERGRID.813 * For grid i, Bi can be expressed in the actual coordinate system814 * by: Bi=[ dh/dx 0 0 0 ]815 * [ 0 dh/dy 0 0 ]816 * [ 0 0 dh/dy 0 ]817 * [ 1/2*dh/dy 1/2*dh/dx 0 0 ]818 * [ 1/2*dh/dz 0 1/2*dh/dx 0 ]819 * [ 0 1/2*dh/dz 1/2*dh/dy 0 ]820 * [ 0 0 0 h ]821 * [ dh/dx dh/dy dh/dz 0 ]822 * where h is the interpolation function for grid i.823 * Same thing for Bb except the last column that does not exist.824 */825 826 int i;827 const int calculationdof=3;828 const int numgrids=6;829 int DOFPERGRID=4;830 831 double dh1dh7[calculationdof][numgrids+1];832 double l1l6[numgrids];833 834 835 /*Get dh1dh7 in actual coordinate system: */836 GetNodalFunctionsMINIDerivatives(&dh1dh7[0][0],xyz_list, gauss_coord);837 GetNodalFunctionsP1(l1l6, gauss_coord);838 839 /*Build B: */840 for (i=0;i<numgrids+1;i++){841 *(B+(DOFPERGRID*numgrids+3)*0+DOFPERGRID*i)=dh1dh7[0][i]; //B[0][DOFPERGRID*i]=dh1dh6[0][i];842 *(B+(DOFPERGRID*numgrids+3)*0+DOFPERGRID*i+1)=0;843 *(B+(DOFPERGRID*numgrids+3)*0+DOFPERGRID*i+2)=0;844 *(B+(DOFPERGRID*numgrids+3)*1+DOFPERGRID*i)=0;845 *(B+(DOFPERGRID*numgrids+3)*1+DOFPERGRID*i+1)=dh1dh7[1][i];846 *(B+(DOFPERGRID*numgrids+3)*1+DOFPERGRID*i+2)=0;847 *(B+(DOFPERGRID*numgrids+3)*2+DOFPERGRID*i)=0;848 *(B+(DOFPERGRID*numgrids+3)*2+DOFPERGRID*i+1)=0;849 *(B+(DOFPERGRID*numgrids+3)*2+DOFPERGRID*i+2)=dh1dh7[2][i];850 *(B+(DOFPERGRID*numgrids+3)*3+DOFPERGRID*i)=(float).5*dh1dh7[1][i];851 *(B+(DOFPERGRID*numgrids+3)*3+DOFPERGRID*i+1)=(float).5*dh1dh7[0][i];852 *(B+(DOFPERGRID*numgrids+3)*3+DOFPERGRID*i+2)=0;853 *(B+(DOFPERGRID*numgrids+3)*4+DOFPERGRID*i)=(float).5*dh1dh7[2][i];854 *(B+(DOFPERGRID*numgrids+3)*4+DOFPERGRID*i+1)=0;855 *(B+(DOFPERGRID*numgrids+3)*4+DOFPERGRID*i+2)=(float).5*dh1dh7[0][i];856 *(B+(DOFPERGRID*numgrids+3)*5+DOFPERGRID*i)=0;857 *(B+(DOFPERGRID*numgrids+3)*5+DOFPERGRID*i+1)=(float).5*dh1dh7[2][i];858 *(B+(DOFPERGRID*numgrids+3)*5+DOFPERGRID*i+2)=(float).5*dh1dh7[1][i];859 *(B+(DOFPERGRID*numgrids+3)*6+DOFPERGRID*i)=0;860 *(B+(DOFPERGRID*numgrids+3)*6+DOFPERGRID*i+1)=0;861 *(B+(DOFPERGRID*numgrids+3)*6+DOFPERGRID*i+2)=0;862 *(B+(DOFPERGRID*numgrids+3)*7+DOFPERGRID*i)=dh1dh7[0][i];863 *(B+(DOFPERGRID*numgrids+3)*7+DOFPERGRID*i+1)=dh1dh7[1][i];864 *(B+(DOFPERGRID*numgrids+3)*7+DOFPERGRID*i+2)=dh1dh7[2][i];865 }866 867 for (i=0;i<numgrids;i++){ //last column not for the bubble function868 *(B+(DOFPERGRID*numgrids+3)*0+DOFPERGRID*i+3)=0;869 *(B+(DOFPERGRID*numgrids+3)*1+DOFPERGRID*i+3)=0;870 *(B+(DOFPERGRID*numgrids+3)*2+DOFPERGRID*i+3)=0;871 *(B+(DOFPERGRID*numgrids+3)*3+DOFPERGRID*i+3)=0;872 *(B+(DOFPERGRID*numgrids+3)*4+DOFPERGRID*i+3)=0;873 *(B+(DOFPERGRID*numgrids+3)*5+DOFPERGRID*i+3)=0;874 *(B+(DOFPERGRID*numgrids+3)*6+DOFPERGRID*i+3)=l1l6[i];875 *(B+(DOFPERGRID*numgrids+3)*7+DOFPERGRID*i+3)=0;876 }877 878 }879 /*}}}*/880 483 /*FUNCTION PentaVertexInput::SquareMin{{{1*/ 881 484 void PentaVertexInput::SquareMin(double* psquaremin, bool process_units,Parameters* parameters){ -
issm/trunk/src/c/objects/Inputs/PentaVertexInput.h
r4882 r4885 64 64 void GetVyStrainRate3dPattyn(double* epsilonvy,double* xyz_list, double* gauss); 65 65 void ChangeEnum(int newenumtype); 66 void GetNodalFunctionsP1(double* l1l6, double* gauss_coord); 67 void GetNodalFunctionsMINI(double* l1l7, double* gauss_coord); 68 void GetNodalFunctionsP1Derivatives(double* dh1dh6,double* xyz_list, double* gauss_coord); 69 void GetNodalFunctionsMINIDerivatives(double* dh1dh7,double* xyz_list, double* gauss_coord); 70 void GetNodalFunctionsP1DerivativesReference(double* dl1dl6,double* gauss_coord); 71 void GetNodalFunctionsMINIDerivativesReference(double* dl1dl7,double* gauss_coord); 72 void GetJacobian(double* J, double* xyz_list,double* gauss_coord); 73 void GetJacobianInvert(double* Jinv, double* xyz_list,double* gauss_coord); 74 void GetBPattyn(double* B, double* xyz_list, double* gauss_coord); 75 void GetBStokes(double* B, double* xyz_list, double* gauss_coord); 66 76 67 void SquareMin(double* psquaremin, bool process_units,Parameters* parameters); 77 68 void Scale(double scale_factor); -
issm/trunk/src/c/objects/Inputs/TriaVertexInput.cpp
r4769 r4885 271 271 272 272 /*Get B matrix: */ 273 GetB (&B[0][0], xyz_list, gauss);273 GetBMacAyeal(&B[0][0], xyz_list, gauss); 274 274 275 275 /*Here, we are computing the strain rate of (vx,0)*/ … … 295 295 296 296 /*Get B matrix: */ 297 GetB (&B[0][0], xyz_list, gauss);297 GetBMacAyeal(&B[0][0], xyz_list, gauss); 298 298 299 299 /*Here, we are computing the strain rate of (0,vy)*/ -
issm/trunk/src/c/shared/Matrix/MatrixUtils.cpp
r3775 r4885 3 3 */ 4 4 5 /* 6 7 TripleMultiply Perform triple matrix product a*b*c+d. 8 9 10 Input: 11 double* a first matrix 12 int nrowa number of rows in a 13 int ncola number of columns in a 14 int itrna transpose flag for a 15 double* b second matrix 16 int nrowb number of rows in b 17 int ncolb number of columns in b 18 int itrnb transpose flag for b 19 double* c third matrix 20 int nrowc number of rows in c 21 int ncolc number of columns in c 22 int itrnc transpose flag for c 23 double* d addition matrix 24 int iaddd addition flag for d 25 26 Output: 27 double* d product matrix 28 int function return value 29 30 */ 5 /*Headers*/ 6 /*{{{1*/ 31 7 #include "./matrix.h" 32 8 #include "../Exceptions/exceptions.h" … … 38 14 #include <float.h> /* DBL_EPSILON */ 39 15 #include "../../include/include.h" 40 16 /*}}}*/ 17 18 /*FUNCTION TripleMultiply {{{1*/ 41 19 int TripleMultiply( double* a, int nrowa, int ncola, int itrna, double* b, int nrowb, int ncolb, int itrnb, double* c, int nrowc, int ncolc, int itrnc, double* d, int iaddd){ 20 /*TripleMultiply Perform triple matrix product a*b*c+d.*/ 42 21 43 22 int idima,idimb,idimc,idimd; … … 116 95 xfree((void **)&dtemp); 117 96 } 118 } 119 120 121 122 123 124 /* 125 126 MatrixMultiply Perform matrix multiplication a*b+c. 127 128 129 Input: 130 double* a first matrix 131 int nrowa number of rows in a 132 int ncola number of columns in a 133 int itrna transpose flag for a 134 double* b second matrix 135 int nrowb number of rows in b 136 int ncolb number of columns in b 137 int itrnb transpose flag for b 138 double* c addition matrix 139 int iaddc addition flag for c 140 141 Output: 142 double* c product matrix 143 int function return value 144 145 */ 146 147 int MatrixMultiply( double* a, 148 int nrowa, 149 int ncola, 150 int itrna, 151 double* b, 152 int nrowb, 153 int ncolb, 154 int itrnb, 155 double* c, 156 int iaddc ) 157 { 97 }/*}}}*/ 98 /*FUNCTION MatrixMuliply {{{1*/ 99 int MatrixMultiply( double* a, int nrowa, int ncola, int itrna, double* b, int nrowb, int ncolb, int itrnb, double* c, int iaddc ){ 100 /*MatrixMultiply Perform matrix multiplication a*b+c.*/ 158 101 int noerr=1; 159 102 int i,j,k,ipta,iptb,iptc; … … 161 104 162 105 /* set up dimensions and increments for matrix a */ 163 164 106 if (!itrna) { 165 107 nrowc=nrowa; … … 168 110 jinca=1; 169 111 } 170 171 112 else { 172 113 nrowc=ncola; … … 177 118 178 119 /* set up dimensions and increments for matrix b */ 179 180 120 if (!itrnb) { 181 121 ncolc=ncolb; … … 184 124 jincb=1; 185 125 } 186 187 126 else { 188 127 ncolc=nrowb; … … 225 164 226 165 return noerr; 227 } 228 229 230 /* 231 232 MatrixInverse Perform matrix inversion and linear equation solution. 233 234 235 Input: 236 double* a coefficient matrix [ndim][ndim] 237 int ndim row and column dimension of a 238 int nrow number of rows in a 239 double* b right-hand vectors [ndim][nvec] (may be nULL) 240 int nvec number of vectors in b (0 for NULL b) 241 242 Output: 243 double* a inverted matrix [ndim][ndim] 244 double* b solution vectors [ndim][nvec] (may be NULL) 245 double* pdet determinant (may be NULL) 246 int error flag 166 }/*}}}*/ 167 /*FUNCTION MatrixInverse {{{1*/ 168 int MatrixInverse( double* a, int ndim, int nrow, double* b, int nvec, double* pdet ){ 169 /* MatrixInverse Perform matrix inversion and linear equation solution. 247 170 248 171 This function uses Gaussian elimination on the original matrix … … 253 176 254 177 Gaussian elimination is inherently inefficient, and so this is 255 intended for small matrices. 256 257 */ 258 259 int MatrixInverse( double* a, 260 int ndim, 261 int nrow, 262 double* b, 263 int nvec, 264 double* pdet ) 265 { 178 intended for small matrices. */ 266 179 int noerr=1; 267 180 int i,j,k,ipt,jpt,irow,icol,ipiv,ncol; … … 424 337 425 338 return noerr; 426 } 339 }/*}}}*/
Note:
See TracChangeset
for help on using the changeset viewer.