[24307] | 1 | Index: ../trunk-jpl/src/c/classes/Elements/Penta.h
|
---|
| 2 | ===================================================================
|
---|
| 3 | --- ../trunk-jpl/src/c/classes/Elements/Penta.h (revision 23800)
|
---|
| 4 | +++ ../trunk-jpl/src/c/classes/Elements/Penta.h (revision 23801)
|
---|
| 5 | @@ -74,10 +74,12 @@
|
---|
| 6 | int GetElementType(void);
|
---|
| 7 | void GetGroundedPart(int* point1,IssmDouble* fraction1, IssmDouble* fraction2,bool* mainlyfloating);
|
---|
| 8 | IssmDouble GetGroundedPortion(IssmDouble* xyz_list);
|
---|
| 9 | + IssmDouble GetIcefrontArea();
|
---|
| 10 | void GetIcefrontCoordinates(IssmDouble** pxyz_front,IssmDouble* xyz_list,int levelsetenum);
|
---|
| 11 | void GetInputValue(IssmDouble* pvalue,Node* node,int enumtype);
|
---|
| 12 | void GetLevelCoordinates(IssmDouble** pxyz_front,IssmDouble* xyz_list,int levelsetenum,IssmDouble level){_error_("not implemented yet");};
|
---|
| 13 | void GetLevelsetPositivePart(int* point1,IssmDouble* fraction1,IssmDouble* fraction2, bool* mainlynegative,IssmDouble* levelsetvalues){_error_("not implemented yet");};
|
---|
| 14 | + void GetLevelsetIntersectionBase(int** pindices, int* pnumiceverts, IssmDouble* fraction, int levelset_enum, IssmDouble level);
|
---|
| 15 | Node* GetNode(int node_number);
|
---|
| 16 | int GetNodeIndex(Node* node);
|
---|
| 17 | int GetNumberOfNodes(void);
|
---|
| 18 | @@ -149,6 +151,7 @@
|
---|
| 19 | void ReduceMatrices(ElementMatrix* Ke,ElementVector* pe);
|
---|
| 20 | void ResetFSBasalBoundaryCondition(void);
|
---|
| 21 | void ResetHooks();
|
---|
| 22 | + void RignotMeltParameterization();
|
---|
| 23 | void SetControlInputsFromVector(IssmDouble* vector,int control_enum,int control_index,int offset, int N,int M);
|
---|
| 24 | void SetControlInputsFromVector(IssmDouble* vector,int control_enum,int control_index);
|
---|
| 25 | void SetCurrentConfiguration(Elements* elements,Loads* loads,Nodes* nodes,Materials* materials,Parameters* parameters);
|
---|
| 26 | Index: ../trunk-jpl/src/c/classes/FemModel.cpp
|
---|
| 27 | ===================================================================
|
---|
| 28 | --- ../trunk-jpl/src/c/classes/FemModel.cpp (revision 23800)
|
---|
| 29 | +++ ../trunk-jpl/src/c/classes/FemModel.cpp (revision 23801)
|
---|
| 30 | @@ -1497,9 +1497,7 @@
|
---|
| 31 | }/*}}}*/
|
---|
| 32 | void FemModel::IcefrontAreax(){/*{{{*/
|
---|
| 33 |
|
---|
| 34 | - int numvertices = this->GetElementsWidth();
|
---|
| 35 | int numbasins;
|
---|
| 36 | - IssmDouble* BasinId = xNew<IssmDouble>(numvertices);
|
---|
| 37 | this->parameters->FindParam(&numbasins,FrontalForcingsNumberofBasinsEnum);
|
---|
| 38 | IssmDouble* basin_icefront_area = xNewZeroInit<IssmDouble>(numbasins);
|
---|
| 39 |
|
---|
| 40 | @@ -1509,24 +1507,27 @@
|
---|
| 41 |
|
---|
| 42 | for(int i=0;i<this->elements->Size();i++){
|
---|
| 43 | Element* element=xDynamicCast<Element*>(this->elements->GetObjectByOffset(i));
|
---|
| 44 | + if(!element->IsOnBase()) continue;
|
---|
| 45 | + int numvertices = element->GetNumberOfVertices();
|
---|
| 46 | + IssmDouble* BasinId = xNew<IssmDouble>(numvertices);
|
---|
| 47 | element->GetInputListOnVertices(BasinId,FrontalForcingsBasinIdEnum);
|
---|
| 48 | - for(int j=0;j<numvertices;j++){
|
---|
| 49 | + for(int j=0;j<3;j++){
|
---|
| 50 | if(BasinId[j]==basin){
|
---|
| 51 | local_icefront_area+=element->GetIcefrontArea();
|
---|
| 52 | break;
|
---|
| 53 | }
|
---|
| 54 | }
|
---|
| 55 | + xDelete<IssmDouble>(BasinId);
|
---|
| 56 | }
|
---|
| 57 | ISSM_MPI_Reduce(&local_icefront_area,&total_icefront_area,1,ISSM_MPI_DOUBLE,ISSM_MPI_SUM,0,IssmComm::GetComm());
|
---|
| 58 | ISSM_MPI_Bcast(&total_icefront_area,1,ISSM_MPI_DOUBLE,0,IssmComm::GetComm());
|
---|
| 59 | -
|
---|
| 60 | +
|
---|
| 61 | basin_icefront_area[basin-1]=total_icefront_area;
|
---|
| 62 | }
|
---|
| 63 |
|
---|
| 64 | this->parameters->AddObject(new DoubleVecParam(FrontalForcingsBasinIcefrontAreaEnum,basin_icefront_area,numbasins));
|
---|
| 65 | + xDelete<IssmDouble>(basin_icefront_area);
|
---|
| 66 |
|
---|
| 67 | - xDelete<IssmDouble>(basin_icefront_area);
|
---|
| 68 | - xDelete<IssmDouble>(BasinId);
|
---|
| 69 | }/*}}}*/
|
---|
| 70 | void FemModel::IceMassx(IssmDouble* pM, bool scaled){/*{{{*/
|
---|
| 71 |
|
---|
| 72 | Index: ../trunk-jpl/src/c/classes/Elements/Penta.cpp
|
---|
| 73 | ===================================================================
|
---|
| 74 | --- ../trunk-jpl/src/c/classes/Elements/Penta.cpp (revision 23800)
|
---|
| 75 | +++ ../trunk-jpl/src/c/classes/Elements/Penta.cpp (revision 23801)
|
---|
| 76 | @@ -1069,6 +1069,107 @@
|
---|
| 77 | return phi;
|
---|
| 78 | }
|
---|
| 79 | /*}}}*/
|
---|
| 80 | +IssmDouble Penta::GetIcefrontArea(){/*{{{*/
|
---|
| 81 | +
|
---|
| 82 | + IssmDouble bed[NUMVERTICES]; //basinId[NUMVERTICES];
|
---|
| 83 | + IssmDouble Haverage,frontarea;
|
---|
| 84 | + IssmDouble x1,y1,x2,y2,distance;
|
---|
| 85 | + IssmDouble lsf[NUMVERTICES], Haux[NUMVERTICES], surfaces[NUMVERTICES], bases[NUMVERTICES];
|
---|
| 86 | + int* indices=NULL;
|
---|
| 87 | + IssmDouble* H=NULL;;
|
---|
| 88 | + int nrfrontbed,numiceverts;
|
---|
| 89 | +
|
---|
| 90 | + /*Retrieve all inputs and parameters*/
|
---|
| 91 | + GetInputListOnVertices(&bed[0],BedEnum);
|
---|
| 92 | + GetInputListOnVertices(&surfaces[0],SurfaceEnum);
|
---|
| 93 | + GetInputListOnVertices(&bases[0],BaseEnum);
|
---|
| 94 | + GetInputListOnVertices(&lsf[0],MaskIceLevelsetEnum);
|
---|
| 95 | +
|
---|
| 96 | + if(!this->IsOnBase()) return 0;
|
---|
| 97 | + if(!IsZeroLevelset(MaskIceLevelsetEnum)) return 0;
|
---|
| 98 | +
|
---|
| 99 | + nrfrontbed=0;
|
---|
| 100 | + for(int i=0;i<NUMVERTICES2D;i++){
|
---|
| 101 | + /*Find if bed<0*/
|
---|
| 102 | + if(bed[i]<0.) nrfrontbed++;
|
---|
| 103 | + }
|
---|
| 104 | +
|
---|
| 105 | + if(nrfrontbed==3){
|
---|
| 106 | + /*2. Find coordinates of where levelset crosses 0*/
|
---|
| 107 | + int numiceverts;
|
---|
| 108 | + IssmDouble s[2],x[2],y[2];
|
---|
| 109 | + this->GetLevelsetIntersectionBase(&indices, &numiceverts,&s[0],MaskIceLevelsetEnum,0.);
|
---|
| 110 | + _assert_(numiceverts);
|
---|
| 111 | +
|
---|
| 112 | + /*3 Write coordinates*/
|
---|
| 113 | + IssmDouble xyz_list[NUMVERTICES][3];
|
---|
| 114 | + ::GetVerticesCoordinates(&xyz_list[0][0],this->vertices,NUMVERTICES);
|
---|
| 115 | + int counter = 0;
|
---|
| 116 | + if((numiceverts>0) && (numiceverts<NUMVERTICES2D)){
|
---|
| 117 | + for(int i=0;i<numiceverts;i++){
|
---|
| 118 | + for(int n=numiceverts;n<NUMVERTICES2D;n++){ // iterate over no-ice vertices
|
---|
| 119 | + x[counter] = xyz_list[indices[i]][0]+s[counter]*(xyz_list[indices[n]][0]-xyz_list[indices[i]][0]);
|
---|
| 120 | + y[counter] = xyz_list[indices[i]][1]+s[counter]*(xyz_list[indices[n]][1]-xyz_list[indices[i]][1]);
|
---|
| 121 | + counter++;
|
---|
| 122 | + }
|
---|
| 123 | + }
|
---|
| 124 | + }
|
---|
| 125 | + else if(numiceverts==NUMVERTICES2D){ //NUMVERTICES ice vertices: calving front lies on element edge
|
---|
| 126 | +
|
---|
| 127 | + for(int i=0;i<NUMVERTICES2D;i++){
|
---|
| 128 | + if(lsf[indices[i]]==0.){
|
---|
| 129 | + x[counter]=xyz_list[indices[i]][0];
|
---|
| 130 | + y[counter]=xyz_list[indices[i]][1];
|
---|
| 131 | + counter++;
|
---|
| 132 | + }
|
---|
| 133 | + if(counter==2) break;
|
---|
| 134 | + }
|
---|
| 135 | + if(counter==1){
|
---|
| 136 | + /*We actually have only 1 vertex on levelset, write a single point as a segment*/
|
---|
| 137 | + x[counter]=x[0];
|
---|
| 138 | + y[counter]=y[0];
|
---|
| 139 | + counter++;
|
---|
| 140 | + }
|
---|
| 141 | + }
|
---|
| 142 | + else{
|
---|
| 143 | + _error_("not sure what's going on here...");
|
---|
| 144 | + }
|
---|
| 145 | + x1=x[0]; y1=y[0]; x2=x[1]; y2=y[1];
|
---|
| 146 | + distance=sqrt(pow((x1-x2),2)+pow((y1-y2),2));
|
---|
| 147 | +
|
---|
| 148 | + int numthk=numiceverts+2;
|
---|
| 149 | + H=xNew<IssmDouble>(numthk);
|
---|
| 150 | + for(int iv=0;iv<NUMVERTICES2D;iv++) Haux[iv]=-bed[indices[iv]]; //sort bed in ice/noice
|
---|
| 151 | +
|
---|
| 152 | + switch(numiceverts){
|
---|
| 153 | + case 1: // average over triangle
|
---|
| 154 | + H[0]=Haux[0];
|
---|
| 155 | + H[1]=Haux[0]+s[0]*(Haux[1]-Haux[0]);
|
---|
| 156 | + H[2]=Haux[0]+s[1]*(Haux[2]-Haux[0]);
|
---|
| 157 | + Haverage=(H[1]+H[2])/2;
|
---|
| 158 | + break;
|
---|
| 159 | + case 2: // average over quadrangle
|
---|
| 160 | + H[0]=Haux[0];
|
---|
| 161 | + H[1]=Haux[1];
|
---|
| 162 | + H[2]=Haux[0]+s[0]*(Haux[2]-Haux[0]);
|
---|
| 163 | + H[3]=Haux[1]+s[1]*(Haux[2]-Haux[1]);
|
---|
| 164 | + Haverage=(H[2]+H[3])/2;
|
---|
| 165 | + break;
|
---|
| 166 | + default:
|
---|
| 167 | + _error_("Number of ice covered vertices wrong in Tria::GetIceFrontArea(void)");
|
---|
| 168 | + break;
|
---|
| 169 | + }
|
---|
| 170 | + frontarea=distance*Haverage;
|
---|
| 171 | + }
|
---|
| 172 | + else return 0;
|
---|
| 173 | +
|
---|
| 174 | + xDelete<int>(indices);
|
---|
| 175 | + xDelete<IssmDouble>(H);
|
---|
| 176 | +
|
---|
| 177 | + _assert_(frontarea>0);
|
---|
| 178 | + return frontarea;
|
---|
| 179 | +}
|
---|
| 180 | +/*}}}*/
|
---|
| 181 | void Penta::GetIcefrontCoordinates(IssmDouble** pxyz_front,IssmDouble* xyz_list,int levelsetenum){/*{{{*/
|
---|
| 182 |
|
---|
| 183 | /* Intermediaries */
|
---|
| 184 | @@ -1132,6 +1233,82 @@
|
---|
| 185 | return lower_penta;
|
---|
| 186 | }
|
---|
| 187 | /*}}}*/
|
---|
| 188 | +void Penta::GetLevelsetIntersectionBase(int** pindices, int* pnumiceverts, IssmDouble* fraction, int levelset_enum, IssmDouble level){/*{{{*/
|
---|
| 189 | +
|
---|
| 190 | + /* GetLevelsetIntersection computes:
|
---|
| 191 | + * 1. indices of element, sorted in [iceverts, noiceverts] in counterclockwise fashion,
|
---|
| 192 | + * 2. fraction of intersected triangle edges intersected by levelset, lying below level*/
|
---|
| 193 | +
|
---|
| 194 | + /*Intermediaries*/
|
---|
| 195 | + int i, numiceverts, numnoiceverts;
|
---|
| 196 | + int ind0, ind1, lastindex;
|
---|
| 197 | + int indices_ice[NUMVERTICES2D],indices_noice[NUMVERTICES2D];
|
---|
| 198 | + IssmDouble lsf[NUMVERTICES];
|
---|
| 199 | + int* indices = xNew<int>(NUMVERTICES2D);
|
---|
| 200 | +
|
---|
| 201 | + /*Retrieve all inputs and parameters*/
|
---|
| 202 | + GetInputListOnVertices(&lsf[0],levelset_enum);
|
---|
| 203 | +
|
---|
| 204 | + /* Determine distribution of ice over element.
|
---|
| 205 | + * Exploit: ice/no-ice parts are connected, so find starting vertex of segment*/
|
---|
| 206 | + lastindex=0;
|
---|
| 207 | + for(i=0;i<NUMVERTICES2D;i++){ // go backwards along vertices, and check for sign change
|
---|
| 208 | + ind0=(NUMVERTICES2D-i)%NUMVERTICES2D;
|
---|
| 209 | + ind1=(ind0-1+NUMVERTICES2D)%NUMVERTICES2D;
|
---|
| 210 | + if((lsf[ind0]-level)*(lsf[ind1]-level)<=0.){ // levelset has been crossed, find last index belonging to segment
|
---|
| 211 | + if(lsf[ind1]==level) //if levelset intersects 2nd vertex, choose this vertex as last
|
---|
| 212 | + lastindex=ind1;
|
---|
| 213 | + else
|
---|
| 214 | + lastindex=ind0;
|
---|
| 215 | + break;
|
---|
| 216 | + }
|
---|
| 217 | + }
|
---|
| 218 | +
|
---|
| 219 | + numiceverts=0;
|
---|
| 220 | + numnoiceverts=0;
|
---|
| 221 | + for(i=0;i<NUMVERTICES2D;i++){
|
---|
| 222 | + ind0=(lastindex+i)%NUMVERTICES2D;
|
---|
| 223 | + if(lsf[i]<=level){
|
---|
| 224 | + indices_ice[numiceverts]=i;
|
---|
| 225 | + numiceverts++;
|
---|
| 226 | + }
|
---|
| 227 | + else{
|
---|
| 228 | + indices_noice[numnoiceverts]=i;
|
---|
| 229 | + numnoiceverts++;
|
---|
| 230 | + }
|
---|
| 231 | + }
|
---|
| 232 | + //merge indices
|
---|
| 233 | + for(i=0;i<numiceverts;i++){indices[i]=indices_ice[i];}
|
---|
| 234 | + for(i=0;i<numnoiceverts;i++){indices[numiceverts+i]=indices_noice[i];}
|
---|
| 235 | +
|
---|
| 236 | + switch (numiceverts){
|
---|
| 237 | + case 0: // no vertex has ice: element is ice free, no intersection
|
---|
| 238 | + for(i=0;i<2;i++)
|
---|
| 239 | + fraction[i]=0.;
|
---|
| 240 | + break;
|
---|
| 241 | + case 1: // one vertex has ice:
|
---|
| 242 | + for(i=0;i<2;i++){
|
---|
| 243 | + fraction[i]=(level-lsf[indices[0]])/(lsf[indices[numiceverts+i]]-lsf[indices[0]]);
|
---|
| 244 | + }
|
---|
| 245 | + break;
|
---|
| 246 | + case 2: // two vertices have ice: fraction is computed from first ice vertex to last in CCW fashion
|
---|
| 247 | + for(i=0;i<2;i++){
|
---|
| 248 | + fraction[i]=(level-lsf[indices[i]])/(lsf[indices[numiceverts]]-lsf[indices[i]]);
|
---|
| 249 | + }
|
---|
| 250 | + break;
|
---|
| 251 | + case NUMVERTICES2D: // all vertices have ice: return triangle area
|
---|
| 252 | + for(i=0;i<2;i++)
|
---|
| 253 | + fraction[i]=1.;
|
---|
| 254 | + break;
|
---|
| 255 | + default:
|
---|
| 256 | + _error_("Wrong number of ice vertices in Penta::GetLevelsetIntersectionBase!");
|
---|
| 257 | + break;
|
---|
| 258 | + }
|
---|
| 259 | +
|
---|
| 260 | + *pindices=indices;
|
---|
| 261 | + *pnumiceverts=numiceverts;
|
---|
| 262 | +}
|
---|
| 263 | +/*}}}*/
|
---|
| 264 | Node* Penta::GetNode(int node_number){/*{{{*/
|
---|
| 265 | _assert_(node_number>=0);
|
---|
| 266 | _assert_(node_number<this->NumberofNodes(this->element_type));
|
---|
| 267 | @@ -2311,6 +2488,65 @@
|
---|
| 268 |
|
---|
| 269 | }
|
---|
| 270 | /*}}}*/
|
---|
| 271 | +void Penta::RignotMeltParameterization(){/*{{{*/
|
---|
| 272 | +
|
---|
| 273 | + IssmDouble A, B, alpha, beta;
|
---|
| 274 | + IssmDouble bed,qsg,qsg_basin,TF,yts;
|
---|
| 275 | + int numbasins;
|
---|
| 276 | + IssmDouble basinid[NUMVERTICES];
|
---|
| 277 | + IssmDouble* basin_icefront_area=NULL;
|
---|
| 278 | +
|
---|
| 279 | + /* Coefficients */
|
---|
| 280 | + A = 3e-4;
|
---|
| 281 | + B = 0.15;
|
---|
| 282 | + alpha = 0.39;
|
---|
| 283 | + beta = 1.18;
|
---|
| 284 | +
|
---|
| 285 | + /*Get inputs*/
|
---|
| 286 | + Input* bed_input = this->GetInput(BedEnum); _assert_(bed_input);
|
---|
| 287 | + Input* qsg_input = this->GetInput(FrontalForcingsSubglacialDischargeEnum); _assert_(qsg_input);
|
---|
| 288 | + Input* TF_input = this->GetInput(FrontalForcingsThermalForcingEnum); _assert_(TF_input);
|
---|
| 289 | + GetInputListOnVertices(&basinid[0],FrontalForcingsBasinIdEnum);
|
---|
| 290 | +
|
---|
| 291 | + this->FindParam(&yts, ConstantsYtsEnum);
|
---|
| 292 | + this->parameters->FindParam(&numbasins,FrontalForcingsNumberofBasinsEnum);
|
---|
| 293 | + this->parameters->FindParam(&basin_icefront_area,&numbasins,FrontalForcingsBasinIcefrontAreaEnum);
|
---|
| 294 | +
|
---|
| 295 | + IssmDouble meltrates[NUMVERTICES2D]; //frontal melt-rate
|
---|
| 296 | +
|
---|
| 297 | + /* Start looping on the number of vertices: */
|
---|
| 298 | + GaussPenta* gauss=new GaussPenta();
|
---|
| 299 | + for(int iv=0;iv<NUMVERTICES2D;iv++){
|
---|
| 300 | + gauss->GaussVertex(iv);
|
---|
| 301 | +
|
---|
| 302 | + /* Get variables */
|
---|
| 303 | + bed_input->GetInputValue(&bed,gauss);
|
---|
| 304 | + qsg_input->GetInputValue(&qsg,gauss);
|
---|
| 305 | + TF_input->GetInputValue(&TF,gauss);
|
---|
| 306 | +
|
---|
| 307 | + if(basin_icefront_area[reCast<int>(basinid[iv])-1]==0.) meltrates[iv]=0.;
|
---|
| 308 | + else{
|
---|
| 309 | + /* change the unit of qsg (m^3/d -> m/d) with ice front area */
|
---|
| 310 | + qsg_basin=qsg/basin_icefront_area[reCast<int>(basinid[iv])-1];
|
---|
| 311 | +
|
---|
| 312 | + /* calculate melt rates */
|
---|
| 313 | + meltrates[iv]=(A*max(-bed,0.)*pow(max(qsg_basin,0.),alpha)+B)*pow(max(TF,0.),beta)/86400; //[m/s]
|
---|
| 314 | + }
|
---|
| 315 | +
|
---|
| 316 | + if(xIsNan<IssmDouble>(meltrates[iv])) _error_("NaN found in vector");
|
---|
| 317 | + if(xIsInf<IssmDouble>(meltrates[iv])) _error_("Inf found in vector");
|
---|
| 318 | + }
|
---|
| 319 | +
|
---|
| 320 | + /*Add input*/
|
---|
| 321 | + this->inputs->AddInput(new PentaInput(CalvingMeltingrateEnum,&meltrates[0],P1Enum));
|
---|
| 322 | +
|
---|
| 323 | + this->InputExtrude(CalvingMeltingrateEnum,-1);
|
---|
| 324 | +
|
---|
| 325 | + /*Cleanup and return*/
|
---|
| 326 | + xDelete<IssmDouble>(basin_icefront_area);
|
---|
| 327 | + delete gauss;
|
---|
| 328 | +}
|
---|
| 329 | +/*}}}*/
|
---|
| 330 | void Penta::SetControlInputsFromVector(IssmDouble* vector,int control_enum,int control_index,int offset, int N, int M){/*{{{*/
|
---|
| 331 |
|
---|
| 332 | IssmDouble values[NUMVERTICES];
|
---|
| 333 | Index: ../trunk-jpl/src/c/classes/Elements/Tria.cpp
|
---|
| 334 | ===================================================================
|
---|
| 335 | --- ../trunk-jpl/src/c/classes/Elements/Tria.cpp (revision 23800)
|
---|
| 336 | +++ ../trunk-jpl/src/c/classes/Elements/Tria.cpp (revision 23801)
|
---|
| 337 | @@ -3419,8 +3419,8 @@
|
---|
| 338 | IssmDouble* basin_icefront_area=NULL;
|
---|
| 339 |
|
---|
| 340 | /* Coefficients */
|
---|
| 341 | - A = 3e-4; //
|
---|
| 342 | - B = 0.15; //
|
---|
| 343 | + A = 3e-4;
|
---|
| 344 | + B = 0.15;
|
---|
| 345 | alpha = 0.39;
|
---|
| 346 | beta = 1.18;
|
---|
| 347 |
|
---|
| 348 | @@ -3457,7 +3457,6 @@
|
---|
| 349 |
|
---|
| 350 | if(xIsNan<IssmDouble>(meltrates[iv])) _error_("NaN found in vector");
|
---|
| 351 | if(xIsInf<IssmDouble>(meltrates[iv])) _error_("Inf found in vector");
|
---|
| 352 | -
|
---|
| 353 | }
|
---|
| 354 |
|
---|
| 355 | /*Add input*/
|
---|