Changeset 1507 for inundation/ga/storm_surge/pyvolution
- Timestamp:
- Jun 9, 2005, 2:49:17 PM (19 years ago)
- Location:
- inundation/ga/storm_surge/pyvolution
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
inundation/ga/storm_surge/pyvolution/shallow_water.py
r1504 r1507 126 126 msg = 'Third conserved quantity must be "ymomentum"' 127 127 assert self.conserved_quantities[2] == 'ymomentum', msg 128 128 129 def extrapolate_second_order_sw(self): 130 #Call correct module function 131 #(either from this module or C-extension) 132 extrapolate_second_order_sw(self) 129 133 130 134 def compute_fluxes(self): … … 253 257 self.writer.store_timestep(name) 254 258 259 ####################MH 090605 new extrapolation function belonging to domain class 260 def extrapolate_second_order_sw(domain): 261 """extrapolate conserved quntities to the vertices of the triangles 262 Python version to be written after the C version 263 """ 264 msg = 'Method extrapolate_second_order_sw should be implemented in C' 265 raise msg 266 ####################MH 090605 ########################################### 255 267 256 268 #Rotation of momentum vector … … 472 484 domain.timestep = timestep 473 485 486 #MH090605 The following method belongs to the shallow_water domain class 487 #see comments in the corresponding method in shallow_water_ext.c 488 def extrapolate_second_order_sw_c(domain): 489 """Wrapper calling C version of extrapolate_second_order_sw 490 """ 491 import sys 492 from Numeric import zeros, Float 493 494 N = domain.number_of_elements 495 496 #Shortcuts 497 Stage = domain.quantities['stage'] 498 Xmom = domain.quantities['xmomentum'] 499 Ymom = domain.quantities['ymomentum'] 500 from shallow_water_ext import extrapolate_second_order_sw 501 extrapolate_second_order_sw(domain,domain.surrogate_neighbours, 502 domain.number_of_boundaries, 503 domain.centroid_coordinates, 504 Stage.centroid_values, 505 Xmom.centroid_values, 506 Ymom.centroid_values, 507 domain.vertex_coordinates, 508 Stage.vertex_values, 509 Xmom.vertex_values, 510 Ymom.vertex_values) 474 511 475 512 def compute_fluxes_c(domain): … … 539 576 540 577 #Extrapolate all conserved quantities 541 for name in domain.conserved_quantities: 542 Q = domain.quantities[name] 543 if domain.order == 1: 578 #MH090605 if second order, perform the extrapolation and limiting on all of the conserved quantities 579 if (domain.order == 1): 580 for name in domain.conserved_quantities: 581 Q = domain.quantities[name] 544 582 Q.extrapolate_first_order() 545 elif domain.order == 2: 546 Q.extrapolate_second_order() 547 Q.limit() 548 else: 549 raise 'Unknown order' 583 elif domain.order == 2: 584 domain.extrapolate_second_order_sw() 585 else: 586 raise 'Unknown order' 587 588 #old code: 589 #for name in domain.conserved_quantities: 590 # Q = domain.quantities[name] 591 # if domain.order == 1: 592 # Q.extrapolate_first_order() 593 # elif domain.order == 2: 594 # #Q.extrapolate_second_order() 595 # Q.limit() 596 # else: 597 # raise 'Unknown order' 550 598 551 599 #Take bed elevation into account when water heights are small … … 1635 1683 from shallow_water_ext import rotate, assign_windfield_values 1636 1684 compute_fluxes = compute_fluxes_c 1685 extrapolate_second_order_sw=extrapolate_second_order_sw_c 1637 1686 gravity = gravity_c 1638 1687 manning_friction = manning_friction_c -
inundation/ga/storm_surge/pyvolution/shallow_water_ext.c
r1505 r1507 47 47 } 48 48 49 49 int find_qmin_and_qmax(double dq0, double dq1, double dq2, double *qmin, double *qmax){ 50 //Considering the centroid of an FV triangle and the vertices of its auxiliary triangle, find 51 //qmin=min(q)-qc and qmax=max(q)-qc, where min(q) and max(q) are respectively min and max over the 52 //four values (at the centroid of the FV triangle and the auxiliary triangle vertices), 53 //and qc is the centroid 54 //dq0=q(vertex0)-q(centroid of FV triangle) 55 //dq1=q(vertex1)-q(vertex0) 56 //dq2=q(vertex2)-q(vertex0) 57 if (dq0>=0.0){ 58 if (dq1>=dq2){ 59 if (dq1>=0.0) 60 *qmax=dq0+dq1; 61 else 62 *qmax=dq0; 63 if ((*qmin=dq0+dq2)<0) 64 ;//qmin is already set to correct value 65 else 66 *qmin=0.0; 67 } 68 else{//dq1<dq2 69 if (dq2>0) 70 *qmax=dq0+dq2; 71 else 72 *qmax=dq0; 73 if ((*qmin=dq0+dq1)<0) 74 ;//qmin is the correct value 75 else 76 *qmin=0.0; 77 } 78 } 79 else{//dq0<0 80 if (dq1<=dq2){ 81 if (dq1<0.0) 82 *qmin=dq0+dq1; 83 else 84 *qmin=dq0; 85 if ((*qmax=dq0+dq2)>0.0) 86 ;//qmax is already set to the correct value 87 else 88 *qmax=0.0; 89 } 90 else{//dq1>dq2 91 if (dq2<0.0) 92 *qmin=dq0+dq2; 93 else 94 *qmin=dq0; 95 if ((*qmax=dq0+dq1)>0.0) 96 ;//qmax is already set to the correct value 97 else 98 *qmax=0.0; 99 } 100 } 101 return 0; 102 } 103 104 int limit_gradient(double *dqv, double qmin, double qmax, double beta_w){ 105 //given provisional jumps dqv from the FV triangle centroid to its vertices and 106 //jumps qmin (qmax) between the centroid of the FV triangle and the 107 //minimum (maximum) of the values at the centroid of the FV triangle and the auxiliary triangle vertices, 108 //calculate a multiplicative factor phi by which the provisional vertex jumps are to be limited 109 int i; 110 double r=1000.0, r0=1.0, phi=1.0; 111 static double TINY = 1.0e-100;//to avoid machine accuracy problems. 112 //Any provisional jump with magnitude < TINY does not contribute to the limiting process. 113 for (i=0;i<3;i++){ 114 if (dqv[i]<-TINY) 115 r0=qmin/dqv[i]; 116 if (dqv[i]>TINY) 117 r0=qmax/dqv[i]; 118 r=min(r0,r); 119 // 120 } 121 phi=min(r*beta_w,1.0); 122 for (i=0;i<3;i++) 123 dqv[i]=dqv[i]*phi; 124 return 0; 125 } 50 126 51 127 // Computational function for flux computation (using stage w=z+h) … … 426 502 return Py_BuildValue(""); 427 503 } 504 505 PyObject *extrapolate_second_order_sw(PyObject *self, PyObject *args) { 506 /*Compute the vertex values based on a linear reconstruction on each triangle 507 These values are calculated as follows: 508 1) For each triangle not adjacent to a boundary, we consider the auxiliary triangle 509 formed by the centroids of its three neighbours. 510 2) For each conserved quantity, we integrate around the auxiliary triangle's boundary the product 511 of the quantity and the outward normal vector. Dividing by the triangle area gives (a,b), the average 512 of the vector (q_x,q_y) on the auxiliary triangle. We suppose that the linear reconstruction on the 513 original triangle has gradient (a,b). 514 3) Provisional vertex junmps dqv[0,1,2] are computed and these are then limited by calling the functions 515 find_qmin_and_qmax and limit_gradient 516 517 Python call: 518 extrapolate_second_order_sw(domain.surrogate_neighbours, 519 domain.number_of_boundaries 520 domain.centroid_coordinates, 521 Stage.centroid_values 522 Xmom.centroid_values 523 Ymom.centroid_values 524 domain.vertex_coordinates, 525 Stage.vertex_values, 526 Xmom.vertex_values, 527 Ymom.vertex_values) 528 529 Post conditions: 530 The vertices of each triangle have values from a limited linear reconstruction 531 based on centroid values 532 533 */ 534 PyArrayObject *surrogate_neighbours, 535 *number_of_boundaries, 536 *centroid_coordinates, 537 *stage_centroid_values, 538 *xmom_centroid_values, 539 *ymom_centroid_values, 540 *vertex_coordinates, 541 *stage_vertex_values, 542 *xmom_vertex_values, 543 *ymom_vertex_values; 544 PyObject *domain, *Tmp; 545 //Local variables 546 double a, b;//gradient vector, not stored but used to calculate vertex values from centroids 547 int number_of_elements,k,k0,k1,k2,k3,k6,coord_index,i; 548 double x,y,x0,y0,x1,y1,x2,y2,xv0,yv0,xv1,yv1,xv2,yv2;//vertices of the auxiliary triangle 549 double dx1,dx2,dy1,dy2,dxv0,dxv1,dxv2,dyv0,dyv1,dyv2,dq0,dq1,dq2,area2; 550 double dqv[3], qmin, qmax, beta_w;//provisional jumps from centroids to v'tices and safety factor re limiting 551 //by which these jumps are limited 552 // Convert Python arguments to C 553 if (!PyArg_ParseTuple(args, "OOOOOOOOOOO", 554 &domain, 555 &surrogate_neighbours, 556 &number_of_boundaries, 557 ¢roid_coordinates, 558 &stage_centroid_values, 559 &xmom_centroid_values, 560 &ymom_centroid_values, 561 &vertex_coordinates, 562 &stage_vertex_values, 563 &xmom_vertex_values, 564 &ymom_vertex_values)) { 565 PyErr_SetString(PyExc_RuntimeError, "Input arguments failed"); 566 return NULL; 567 } 568 569 //get the safety factor beta_w, set in the config.py file. This is used in the limiting process 570 Tmp = PyObject_GetAttrString(domain, "beta_w"); 571 if (!Tmp) 572 return NULL; 573 beta_w = PyFloat_AsDouble(Tmp); 574 Py_DECREF(Tmp); 575 number_of_elements = stage_centroid_values -> dimensions[0]; 576 for (k=0; k<number_of_elements; k++) { 577 k3=k*3; 578 k6=k*6; 579 580 if (((long *) number_of_boundaries->data)[k]==3){/*no neighbours, set gradient on the triangle to zero*/ 581 ((double *) stage_vertex_values->data)[k3]=((double *)stage_centroid_values->data)[k]; 582 ((double *) stage_vertex_values->data)[k3+1]=((double *)stage_centroid_values->data)[k]; 583 ((double *) stage_vertex_values->data)[k3+2]=((double *)stage_centroid_values->data)[k]; 584 ((double *) xmom_vertex_values->data)[k3]=((double *)xmom_centroid_values->data)[k]; 585 ((double *) xmom_vertex_values->data)[k3+1]=((double *)xmom_centroid_values->data)[k]; 586 ((double *) xmom_vertex_values->data)[k3+2]=((double *)xmom_centroid_values->data)[k]; 587 ((double *) ymom_vertex_values->data)[k3]=((double *)ymom_centroid_values->data)[k]; 588 ((double *) ymom_vertex_values->data)[k3+1]=((double *)ymom_centroid_values->data)[k]; 589 ((double *) ymom_vertex_values->data)[k3+2]=((double *)ymom_centroid_values->data)[k]; 590 continue; 591 } 592 else {//we will need centroid coordinates and vertex coordinates of the triangle 593 //get the vertex coordinates of the FV triangle 594 xv0=((double *)vertex_coordinates->data)[k6]; yv0=((double *)vertex_coordinates->data)[k6+1]; 595 xv1=((double *)vertex_coordinates->data)[k6+2]; yv1=((double *)vertex_coordinates->data)[k6+3]; 596 xv2=((double *)vertex_coordinates->data)[k6+4]; yv2=((double *)vertex_coordinates->data)[k6+5]; 597 //get the centroid coordinates of the FV triangle 598 coord_index=2*k; 599 x=((double *)centroid_coordinates->data)[coord_index]; 600 y=((double *)centroid_coordinates->data)[coord_index+1]; 601 //store x- and y- differentials for the vertices of the FV triangle relative to the centroid 602 dxv0=xv0-x; dxv1=xv1-x; dxv2=xv2-x; 603 dyv0=yv0-y; dyv1=yv1-y; dyv2=yv2-y; 604 } 605 if (((long *)number_of_boundaries->data)[k]<=1){ 606 //if no boundaries, auxiliary triangle is formed from the centroids of the three neighbours 607 //if one boundary, auxiliary triangle is formed from this centroid and its two neighbours 608 k0=((long *)surrogate_neighbours->data)[k3]; 609 k1=((long *)surrogate_neighbours->data)[k3+1]; 610 k2=((long *)surrogate_neighbours->data)[k3+2]; 611 //get the auxiliary triangle's vertex coordinates (really the centroids of neighbouring triangles) 612 coord_index=2*k0; 613 x0=((double *)centroid_coordinates->data)[coord_index]; 614 y0=((double *)centroid_coordinates->data)[coord_index+1]; 615 coord_index=2*k1; 616 x1=((double *)centroid_coordinates->data)[coord_index]; 617 y1=((double *)centroid_coordinates->data)[coord_index+1]; 618 coord_index=2*k2; 619 x2=((double *)centroid_coordinates->data)[coord_index]; 620 y2=((double *)centroid_coordinates->data)[coord_index+1]; 621 //store x- and y- differentials for the vertices of the auxiliary triangle 622 dx1=x1-x0; dx2=x2-x0; 623 dy1=y1-y0; dy2=y2-y0; 624 //calculate 2*area of the auxiliary triangle 625 area2 = dy2*dx1 - dy1*dx2;//the triangle is guaranteed to be counter-clockwise 626 //If the mesh is 'weird' near the boundary, the trianlge might be flat or clockwise: 627 if (area2<=0) 628 return NULL; 629 630 //### stage ### 631 //calculate the difference between vertex 0 of the auxiliary triangle and the FV triangle centroid 632 dq0=((double *)stage_centroid_values->data)[k0]-((double *)stage_centroid_values->data)[k]; 633 //calculate differentials between the vertices of the auxiliary triangle 634 dq1=((double *)stage_centroid_values->data)[k1]-((double *)stage_centroid_values->data)[k0]; 635 dq2=((double *)stage_centroid_values->data)[k2]-((double *)stage_centroid_values->data)[k0]; 636 //calculate the gradient of stage on the auxiliary triangle 637 a = dy2*dq1 - dy1*dq2; 638 a /= area2; 639 b = dx1*dq2 - dx2*dq1; 640 b /= area2; 641 //calculate provisional jumps in stage from the centroid of the FV tri to its vertices, to be limited 642 dqv[0]=a*dxv0+b*dyv0; 643 dqv[1]=a*dxv1+b*dyv1; 644 dqv[2]=a*dxv2+b*dyv2; 645 //now we want to find min and max of the centroid and the vertices of the auxiliary triangle 646 //and compute jumps from the centroid to the min and max 647 find_qmin_and_qmax(dq0,dq1,dq2,&qmin,&qmax); 648 limit_gradient(dqv,qmin,qmax,beta_w);//the gradient will be limited 649 for (i=0;i<3;i++) 650 ((double *)stage_vertex_values->data)[k3+i]=((double *)stage_centroid_values->data)[k]+dqv[i]; 651 652 //### xmom ### 653 //calculate the difference between vertex 0 of the auxiliary triangle and the FV triangle centroid 654 dq0=((double *)xmom_centroid_values->data)[k0]-((double *)xmom_centroid_values->data)[k]; 655 //calculate differentials between the vertices of the auxiliary triangle 656 dq1=((double *)xmom_centroid_values->data)[k1]-((double *)xmom_centroid_values->data)[k0]; 657 dq2=((double *)xmom_centroid_values->data)[k2]-((double *)xmom_centroid_values->data)[k0]; 658 //calculate the gradient of xmom on the auxiliary triangle 659 a = dy2*dq1 - dy1*dq2; 660 a /= area2; 661 b = dx1*dq2 - dx2*dq1; 662 b /= area2; 663 //calculate provisional jumps in stage from the centroid of the FV tri to its vertices, to be limited 664 dqv[0]=a*dxv0+b*dyv0; 665 dqv[1]=a*dxv1+b*dyv1; 666 dqv[2]=a*dxv2+b*dyv2; 667 //now we want to find min and max of the centroid and the vertices of the auxiliary triangle 668 //and compute jumps from the centroid to the min and max 669 find_qmin_and_qmax(dq0,dq1,dq2,&qmin,&qmax); 670 limit_gradient(dqv,qmin,qmax,beta_w);//the gradient will be limited 671 for (i=0;i<3;i++) 672 ((double *)xmom_vertex_values->data)[k3+i]=((double *)xmom_centroid_values->data)[k]+dqv[i]; 673 674 //### ymom ### 675 //calculate the difference between vertex 0 of the auxiliary triangle and the FV triangle centroid 676 dq0=((double *)ymom_centroid_values->data)[k0]-((double *)ymom_centroid_values->data)[k]; 677 //calculate differentials between the vertices of the auxiliary triangle 678 dq1=((double *)ymom_centroid_values->data)[k1]-((double *)ymom_centroid_values->data)[k0]; 679 dq2=((double *)ymom_centroid_values->data)[k2]-((double *)ymom_centroid_values->data)[k0]; 680 //calculate the gradient of xmom on the auxiliary triangle 681 a = dy2*dq1 - dy1*dq2; 682 a /= area2; 683 b = dx1*dq2 - dx2*dq1; 684 b /= area2; 685 //calculate provisional jumps in stage from the centroid of the FV tri to its vertices, to be limited 686 dqv[0]=a*dxv0+b*dyv0; 687 dqv[1]=a*dxv1+b*dyv1; 688 dqv[2]=a*dxv2+b*dyv2; 689 //now we want to find min and max of the centroid and the vertices of the auxiliary triangle 690 //and compute jumps from the centroid to the min and max 691 find_qmin_and_qmax(dq0,dq1,dq2,&qmin,&qmax); 692 limit_gradient(dqv,qmin,qmax,beta_w);//the gradient will be limited 693 for (i=0;i<3;i++) 694 ((double *)ymom_vertex_values->data)[k3+i]=((double *)ymom_centroid_values->data)[k]+dqv[i]; 695 }//if (number_of_boundaries[k]<=1) 696 else{//number_of_boundaries==2 697 //one internal neighbour and gradient is in direction of the neighbour's centroid 698 //find the only internal neighbour 699 for (k2=k3;k2<k3+3;k2++){//k2 just indexes the edges of triangle k 700 if (((long *)surrogate_neighbours->data)[k2]!=k)//find internal neighbour of triabngle k 701 break; 702 } 703 if ((k2==k3+3))//if we didn't find an internal neighbour 704 return NULL;//error 705 k1=((long *)surrogate_neighbours->data)[k2]; 706 //the coordinates of the triangle are already (x,y). Get centroid of the neighbour (x1,y1) 707 coord_index=2*k1; 708 x1=((double *)centroid_coordinates->data)[coord_index]; 709 y1=((double *)centroid_coordinates->data)[coord_index+1]; 710 //compute x- and y- distances between the centroid of the FV triangle and that of its neighbour 711 dx1=x1-x; dy1=y1-y; 712 //set area2 as the square of the distance 713 area2=dx1*dx1+dy1*dy1; 714 //set dx2=(x1-x0)/((x1-x0)^2+(y1-y0)^2) and dy2=(y1-y0)/((x1-x0)^2+(y1-y0)^2) which 715 //respectively correspond to the x- and y- gradients of the conserved quantities 716 dx2=1.0/area2; 717 dy2=dx2*dy1; 718 dx2*=dx1; 719 720 //## stage ### 721 //compute differentials 722 dq1=((double *)stage_centroid_values->data)[k1]-((double *)stage_centroid_values->data)[k]; 723 //calculate the gradient between the centroid of the FV triangle and that of its neighbour 724 a=dq1*dx2; 725 b=dq1*dy2; 726 //calculate provisional vertex jumps, to be limited 727 dqv[0]=a*dxv0+b*dyv0; 728 dqv[1]=a*dxv1+b*dyv1; 729 dqv[2]=a*dxv2+b*dyv2; 730 //now limit the jumps 731 if (dq1>=0.0){ 732 qmin=0.0; 733 qmax=dq1; 734 } 735 else{ 736 qmin=dq1; 737 qmax=0.0; 738 } 739 limit_gradient(dqv,qmin,qmax,beta_w);//the gradient will be limited 740 for (i=0;i<3;i++) 741 ((double *)stage_vertex_values->data)[k3+i]=((double *)stage_centroid_values->data)[k]+dqv[i]; 742 743 //## xmom ### 744 //compute differentials 745 dq1=((double *)xmom_centroid_values->data)[k1]-((double *)xmom_centroid_values->data)[k]; 746 //calculate the gradient between the centroid of the FV triangle and that of its neighbour 747 a=dq1*dx2; 748 b=dq1*dy2; 749 //calculate provisional vertex jumps, to be limited 750 dqv[0]=a*dxv0+b*dyv0; 751 dqv[1]=a*dxv1+b*dyv1; 752 dqv[2]=a*dxv2+b*dyv2; 753 //now limit the jumps 754 if (dq1>=0.0){ 755 qmin=0.0; 756 qmax=dq1; 757 } 758 else{ 759 qmin=dq1; 760 qmax=0.0; 761 } 762 limit_gradient(dqv,qmin,qmax,beta_w);//the gradient will be limited 763 for (i=0;i<3;i++) 764 ((double *)xmom_vertex_values->data)[k3+i]=((double *)xmom_centroid_values->data)[k]+dqv[i]; 765 766 //## ymom ### 767 //compute differentials 768 dq1=((double *)ymom_centroid_values->data)[k1]-((double *)ymom_centroid_values->data)[k]; 769 //calculate the gradient between the centroid of the FV triangle and that of its neighbour 770 a=dq1*dx2; 771 b=dq1*dy2; 772 //calculate provisional vertex jumps, to be limited 773 dqv[0]=a*dxv0+b*dyv0; 774 dqv[1]=a*dxv1+b*dyv1; 775 dqv[2]=a*dxv2+b*dyv2; 776 //now limit the jumps 777 if (dq1>=0.0){ 778 qmin=0.0; 779 qmax=dq1; 780 } 781 else{ 782 qmin=dq1; 783 qmax=0.0; 784 } 785 limit_gradient(dqv,qmin,qmax,beta_w);//the gradient will be limited 786 for (i=0;i<3;i++) 787 ((double *)ymom_vertex_values->data)[k3+i]=((double *)ymom_centroid_values->data)[k]+dqv[i]; 788 }//else [number_of_boudaries==2] 789 }//for k=0 to number_of_elements-1 790 return Py_BuildValue(""); 791 }//extrapolate_second-order_sw 428 792 429 793 PyObject *rotate(PyObject *self, PyObject *args, PyObject *kwargs) { … … 866 1230 867 1231 {"rotate", (PyCFunction)rotate, METH_VARARGS | METH_KEYWORDS, "Print out"}, 1232 {"extrapolate_second_order_sw", extrapolate_second_order_sw, METH_VARARGS, "Print out"}, 868 1233 {"compute_fluxes", compute_fluxes, METH_VARARGS, "Print out"}, 869 1234 {"gravity", gravity, METH_VARARGS, "Print out"},
Note: See TracChangeset
for help on using the changeset viewer.