Changeset 1641
- Timestamp:
- Jul 26, 2005, 5:16:04 PM (20 years ago)
- Location:
- inundation/ga/storm_surge/pyvolution
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
inundation/ga/storm_surge/pyvolution/shallow_water.py
r1636 r1641 56 56 57 57 from domain import * 58 from region import * 58 from region import *# 59 59 60 Generic_domain = Domain #Rename 60 61 … … 81 82 #Realtime visualisation 82 83 self.visualiser = None 83 self.visualise = False84 self.visualise = False 84 85 self.visualise_color_stage = False 85 86 self.visualise_stage_range = 1.0 … … 107 108 #self.eta = self.quantities['friction'] 108 109 110 def initialise_visualiser(self,scale_z=1.0,rect=None): 111 #Realtime visualisation 112 if self.visualiser is None: 113 from realtime_visualisation_new import Visualiser 114 self.visualiser = Visualiser(self,scale_z,rect) 115 self.visualise = True 116 109 117 def check_integrity(self): 110 118 Generic_domain.check_integrity(self) … … 119 127 assert self.conserved_quantities[2] == 'ymomentum', msg 120 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) 121 133 122 134 def compute_fluxes(self): … … 250 262 self.writer.store_timestep(name) 251 263 264 ####################MH 090605 new extrapolation function belonging to domain class 265 def extrapolate_second_order_sw(domain): 266 """extrapolate conserved quntities to the vertices of the triangles 267 Python version to be written after the C version 268 """ 269 msg = 'Method extrapolate_second_order_sw should be implemented in C' 270 raise msg 271 ####################MH 090605 ########################################### 252 272 253 273 def initialise_visualiser(self,scale_z=1.0,rect=None): … … 436 456 437 457 flux = zeros(3, Float) #Work array for summing up fluxes 458 438 459 439 460 #Loop … … 482 503 domain.timestep = timestep 483 504 505 #MH090605 The following method belongs to the shallow_water domain class 506 #see comments in the corresponding method in shallow_water_ext.c 507 def extrapolate_second_order_sw_c(domain): 508 """Wrapper calling C version of extrapolate_second_order_sw 509 """ 510 import sys 511 from Numeric import zeros, Float 512 513 N = domain.number_of_elements 514 515 #Shortcuts 516 Stage = domain.quantities['stage'] 517 Xmom = domain.quantities['xmomentum'] 518 Ymom = domain.quantities['ymomentum'] 519 from shallow_water_ext import extrapolate_second_order_sw 520 extrapolate_second_order_sw(domain,domain.surrogate_neighbours, 521 domain.number_of_boundaries, 522 domain.centroid_coordinates, 523 Stage.centroid_values, 524 Xmom.centroid_values, 525 Ymom.centroid_values, 526 domain.vertex_coordinates, 527 Stage.vertex_values, 528 Xmom.vertex_values, 529 Ymom.vertex_values) 484 530 485 531 def compute_fluxes_c(domain): … … 516 562 Stage.explicit_update, 517 563 Xmom.explicit_update, 518 Ymom.explicit_update) 564 Ymom.explicit_update, 565 domain.already_computed_flux) 519 566 520 567 … … 545 592 """ 546 593 594 from config import optimised_gradient_limiter 595 547 596 #Remove very thin layers of water 548 597 protect_against_infinitesimal_and_negative_heights(domain) 549 598 550 599 #Extrapolate all conserved quantities 551 for name in domain.conserved_quantities: 552 Q = domain.quantities[name] 553 if domain.order == 1: 554 Q.extrapolate_first_order() 600 if optimised_gradient_limiter: 601 #MH090605 if second order, 602 #perform the extrapolation and limiting on 603 #all of the conserved quantitie 604 605 if (domain.order == 1): 606 for name in domain.conserved_quantities: 607 Q = domain.quantities[name] 608 Q.extrapolate_first_order() 555 609 elif domain.order == 2: 556 Q.extrapolate_second_order() 557 Q.limit() 610 domain.extrapolate_second_order_sw() 558 611 else: 559 612 raise 'Unknown order' 613 else: 614 #old code: 615 for name in domain.conserved_quantities: 616 Q = domain.quantities[name] 617 if domain.order == 1: 618 Q.extrapolate_first_order() 619 elif domain.order == 2: 620 Q.extrapolate_second_order() 621 Q.limit() 622 else: 623 raise 'Unknown order' 624 560 625 561 626 #Take bed elevation into account when water heights are small … … 738 803 739 804 #Call C-extension 740 from shallow_water_ext import h_limiter 805 from shallow_water_ext import h_limiter_sw as h_limiter 741 806 hvbar = h_limiter(domain, hc, hv) 742 807 … … 909 974 raise msg 910 975 911 912 self.stage= domain.quantities['stage'].edge_values913 self.xmom= domain.quantities['xmomentum'].edge_values914 self.ymom= domain.quantities['ymomentum'].edge_values915 916 917 918 976 #Handy shorthands 977 self.stage = domain.quantities['stage'].edge_values 978 self.xmom = domain.quantities['xmomentum'].edge_values 979 self.ymom = domain.quantities['ymomentum'].edge_values 980 self.normals = domain.normals 981 982 from Numeric import zeros, Float 983 self.conserved_quantities = zeros(3, Float) 919 984 920 985 def __repr__(self): … … 927 992 """ 928 993 929 930 931 932 933 934 994 q = self.conserved_quantities 995 q[0] = self.stage[vol_id, edge_id] 996 q[1] = self.xmom[vol_id, edge_id] 997 q[2] = self.ymom[vol_id, edge_id] 998 999 normal = self.normals[vol_id, 2*edge_id:2*edge_id+2] 935 1000 936 1001 … … 1647 1712 from shallow_water_ext import rotate, assign_windfield_values 1648 1713 compute_fluxes = compute_fluxes_c 1714 extrapolate_second_order_sw=extrapolate_second_order_sw_c 1649 1715 gravity = gravity_c 1650 1716 manning_friction = manning_friction_c -
inundation/ga/storm_surge/pyvolution/shallow_water_ext.c
r1636 r1641 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) … … 170 246 if (h >= eps) { 171 247 S = -g * eta[k]*eta[k] * sqrt((uh[k]*uh[k] + vh[k]*vh[k])); 172 S /= pow(h, 7.0/3); //Expensive (on Ole's home computer) 248 //S /= pow(h, 7.0/3); //Expensive (on Ole's home computer) 249 S /= exp(7.0/3.0*log(h)); //seems to save about 15% over manning_friction 173 250 //S /= h*h*(1 + h/3.0 - h*h/9.0); //FIXME: Could use a Taylor expansion 174 251 … … 423 500 } 424 501 502 PyObject *extrapolate_second_order_sw(PyObject *self, PyObject *args) { 503 /*Compute the vertex values based on a linear reconstruction on each triangle 504 These values are calculated as follows: 505 1) For each triangle not adjacent to a boundary, we consider the auxiliary triangle 506 formed by the centroids of its three neighbours. 507 2) For each conserved quantity, we integrate around the auxiliary triangle's boundary the product 508 of the quantity and the outward normal vector. Dividing by the triangle area gives (a,b), the average 509 of the vector (q_x,q_y) on the auxiliary triangle. We suppose that the linear reconstruction on the 510 original triangle has gradient (a,b). 511 3) Provisional vertex junmps dqv[0,1,2] are computed and these are then limited by calling the functions 512 find_qmin_and_qmax and limit_gradient 513 514 Python call: 515 extrapolate_second_order_sw(domain.surrogate_neighbours, 516 domain.number_of_boundaries 517 domain.centroid_coordinates, 518 Stage.centroid_values 519 Xmom.centroid_values 520 Ymom.centroid_values 521 domain.vertex_coordinates, 522 Stage.vertex_values, 523 Xmom.vertex_values, 524 Ymom.vertex_values) 525 526 Post conditions: 527 The vertices of each triangle have values from a limited linear reconstruction 528 based on centroid values 529 530 */ 531 PyArrayObject *surrogate_neighbours, 532 *number_of_boundaries, 533 *centroid_coordinates, 534 *stage_centroid_values, 535 *xmom_centroid_values, 536 *ymom_centroid_values, 537 *vertex_coordinates, 538 *stage_vertex_values, 539 *xmom_vertex_values, 540 *ymom_vertex_values; 541 PyObject *domain, *Tmp; 542 //Local variables 543 double a, b;//gradient vector, not stored but used to calculate vertex values from centroids 544 int number_of_elements,k,k0,k1,k2,k3,k6,coord_index,i; 545 double x,y,x0,y0,x1,y1,x2,y2,xv0,yv0,xv1,yv1,xv2,yv2;//vertices of the auxiliary triangle 546 double dx1,dx2,dy1,dy2,dxv0,dxv1,dxv2,dyv0,dyv1,dyv2,dq0,dq1,dq2,area2; 547 double dqv[3], qmin, qmax, beta_w;//provisional jumps from centroids to v'tices and safety factor re limiting 548 //by which these jumps are limited 549 // Convert Python arguments to C 550 if (!PyArg_ParseTuple(args, "OOOOOOOOOOO", 551 &domain, 552 &surrogate_neighbours, 553 &number_of_boundaries, 554 ¢roid_coordinates, 555 &stage_centroid_values, 556 &xmom_centroid_values, 557 &ymom_centroid_values, 558 &vertex_coordinates, 559 &stage_vertex_values, 560 &xmom_vertex_values, 561 &ymom_vertex_values)) { 562 PyErr_SetString(PyExc_RuntimeError, "Input arguments failed"); 563 return NULL; 564 } 565 566 //get the safety factor beta_w, set in the config.py file. This is used in the limiting process 567 Tmp = PyObject_GetAttrString(domain, "beta_w"); 568 if (!Tmp) 569 return NULL; 570 beta_w = PyFloat_AsDouble(Tmp); 571 Py_DECREF(Tmp); 572 number_of_elements = stage_centroid_values -> dimensions[0]; 573 for (k=0; k<number_of_elements; k++) { 574 k3=k*3; 575 k6=k*6; 576 577 if (((long *) number_of_boundaries->data)[k]==3){/*no neighbours, set gradient on the triangle to zero*/ 578 ((double *) stage_vertex_values->data)[k3]=((double *)stage_centroid_values->data)[k]; 579 ((double *) stage_vertex_values->data)[k3+1]=((double *)stage_centroid_values->data)[k]; 580 ((double *) stage_vertex_values->data)[k3+2]=((double *)stage_centroid_values->data)[k]; 581 ((double *) xmom_vertex_values->data)[k3]=((double *)xmom_centroid_values->data)[k]; 582 ((double *) xmom_vertex_values->data)[k3+1]=((double *)xmom_centroid_values->data)[k]; 583 ((double *) xmom_vertex_values->data)[k3+2]=((double *)xmom_centroid_values->data)[k]; 584 ((double *) ymom_vertex_values->data)[k3]=((double *)ymom_centroid_values->data)[k]; 585 ((double *) ymom_vertex_values->data)[k3+1]=((double *)ymom_centroid_values->data)[k]; 586 ((double *) ymom_vertex_values->data)[k3+2]=((double *)ymom_centroid_values->data)[k]; 587 continue; 588 } 589 else {//we will need centroid coordinates and vertex coordinates of the triangle 590 //get the vertex coordinates of the FV triangle 591 xv0=((double *)vertex_coordinates->data)[k6]; yv0=((double *)vertex_coordinates->data)[k6+1]; 592 xv1=((double *)vertex_coordinates->data)[k6+2]; yv1=((double *)vertex_coordinates->data)[k6+3]; 593 xv2=((double *)vertex_coordinates->data)[k6+4]; yv2=((double *)vertex_coordinates->data)[k6+5]; 594 //get the centroid coordinates of the FV triangle 595 coord_index=2*k; 596 x=((double *)centroid_coordinates->data)[coord_index]; 597 y=((double *)centroid_coordinates->data)[coord_index+1]; 598 //store x- and y- differentials for the vertices of the FV triangle relative to the centroid 599 dxv0=xv0-x; dxv1=xv1-x; dxv2=xv2-x; 600 dyv0=yv0-y; dyv1=yv1-y; dyv2=yv2-y; 601 } 602 if (((long *)number_of_boundaries->data)[k]<=1){ 603 //if no boundaries, auxiliary triangle is formed from the centroids of the three neighbours 604 //if one boundary, auxiliary triangle is formed from this centroid and its two neighbours 605 k0=((long *)surrogate_neighbours->data)[k3]; 606 k1=((long *)surrogate_neighbours->data)[k3+1]; 607 k2=((long *)surrogate_neighbours->data)[k3+2]; 608 //get the auxiliary triangle's vertex coordinates (really the centroids of neighbouring triangles) 609 coord_index=2*k0; 610 x0=((double *)centroid_coordinates->data)[coord_index]; 611 y0=((double *)centroid_coordinates->data)[coord_index+1]; 612 coord_index=2*k1; 613 x1=((double *)centroid_coordinates->data)[coord_index]; 614 y1=((double *)centroid_coordinates->data)[coord_index+1]; 615 coord_index=2*k2; 616 x2=((double *)centroid_coordinates->data)[coord_index]; 617 y2=((double *)centroid_coordinates->data)[coord_index+1]; 618 //store x- and y- differentials for the vertices of the auxiliary triangle 619 dx1=x1-x0; dx2=x2-x0; 620 dy1=y1-y0; dy2=y2-y0; 621 //calculate 2*area of the auxiliary triangle 622 area2 = dy2*dx1 - dy1*dx2;//the triangle is guaranteed to be counter-clockwise 623 //If the mesh is 'weird' near the boundary, the trianlge might be flat or clockwise: 624 if (area2<=0) 625 return NULL; 626 627 //### stage ### 628 //calculate the difference between vertex 0 of the auxiliary triangle and the FV triangle centroid 629 dq0=((double *)stage_centroid_values->data)[k0]-((double *)stage_centroid_values->data)[k]; 630 //calculate differentials between the vertices of the auxiliary triangle 631 dq1=((double *)stage_centroid_values->data)[k1]-((double *)stage_centroid_values->data)[k0]; 632 dq2=((double *)stage_centroid_values->data)[k2]-((double *)stage_centroid_values->data)[k0]; 633 //calculate the gradient of stage on the auxiliary triangle 634 a = dy2*dq1 - dy1*dq2; 635 a /= area2; 636 b = dx1*dq2 - dx2*dq1; 637 b /= area2; 638 //calculate provisional jumps in stage from the centroid of the FV tri to its vertices, to be limited 639 dqv[0]=a*dxv0+b*dyv0; 640 dqv[1]=a*dxv1+b*dyv1; 641 dqv[2]=a*dxv2+b*dyv2; 642 //now we want to find min and max of the centroid and the vertices of the auxiliary triangle 643 //and compute jumps from the centroid to the min and max 644 find_qmin_and_qmax(dq0,dq1,dq2,&qmin,&qmax); 645 limit_gradient(dqv,qmin,qmax,beta_w);//the gradient will be limited 646 for (i=0;i<3;i++) 647 ((double *)stage_vertex_values->data)[k3+i]=((double *)stage_centroid_values->data)[k]+dqv[i]; 648 649 //### xmom ### 650 //calculate the difference between vertex 0 of the auxiliary triangle and the FV triangle centroid 651 dq0=((double *)xmom_centroid_values->data)[k0]-((double *)xmom_centroid_values->data)[k]; 652 //calculate differentials between the vertices of the auxiliary triangle 653 dq1=((double *)xmom_centroid_values->data)[k1]-((double *)xmom_centroid_values->data)[k0]; 654 dq2=((double *)xmom_centroid_values->data)[k2]-((double *)xmom_centroid_values->data)[k0]; 655 //calculate the gradient of xmom on the auxiliary triangle 656 a = dy2*dq1 - dy1*dq2; 657 a /= area2; 658 b = dx1*dq2 - dx2*dq1; 659 b /= area2; 660 //calculate provisional jumps in stage from the centroid of the FV tri to its vertices, to be limited 661 dqv[0]=a*dxv0+b*dyv0; 662 dqv[1]=a*dxv1+b*dyv1; 663 dqv[2]=a*dxv2+b*dyv2; 664 //now we want to find min and max of the centroid and the vertices of the auxiliary triangle 665 //and compute jumps from the centroid to the min and max 666 find_qmin_and_qmax(dq0,dq1,dq2,&qmin,&qmax); 667 limit_gradient(dqv,qmin,qmax,beta_w);//the gradient will be limited 668 for (i=0;i<3;i++) 669 ((double *)xmom_vertex_values->data)[k3+i]=((double *)xmom_centroid_values->data)[k]+dqv[i]; 670 671 //### ymom ### 672 //calculate the difference between vertex 0 of the auxiliary triangle and the FV triangle centroid 673 dq0=((double *)ymom_centroid_values->data)[k0]-((double *)ymom_centroid_values->data)[k]; 674 //calculate differentials between the vertices of the auxiliary triangle 675 dq1=((double *)ymom_centroid_values->data)[k1]-((double *)ymom_centroid_values->data)[k0]; 676 dq2=((double *)ymom_centroid_values->data)[k2]-((double *)ymom_centroid_values->data)[k0]; 677 //calculate the gradient of xmom on the auxiliary triangle 678 a = dy2*dq1 - dy1*dq2; 679 a /= area2; 680 b = dx1*dq2 - dx2*dq1; 681 b /= area2; 682 //calculate provisional jumps in stage from the centroid of the FV tri to its vertices, to be limited 683 dqv[0]=a*dxv0+b*dyv0; 684 dqv[1]=a*dxv1+b*dyv1; 685 dqv[2]=a*dxv2+b*dyv2; 686 //now we want to find min and max of the centroid and the vertices of the auxiliary triangle 687 //and compute jumps from the centroid to the min and max 688 find_qmin_and_qmax(dq0,dq1,dq2,&qmin,&qmax); 689 limit_gradient(dqv,qmin,qmax,beta_w);//the gradient will be limited 690 for (i=0;i<3;i++) 691 ((double *)ymom_vertex_values->data)[k3+i]=((double *)ymom_centroid_values->data)[k]+dqv[i]; 692 }//if (number_of_boundaries[k]<=1) 693 else{//number_of_boundaries==2 694 //one internal neighbour and gradient is in direction of the neighbour's centroid 695 //find the only internal neighbour 696 for (k2=k3;k2<k3+3;k2++){//k2 just indexes the edges of triangle k 697 if (((long *)surrogate_neighbours->data)[k2]!=k)//find internal neighbour of triabngle k 698 break; 699 } 700 if ((k2==k3+3))//if we didn't find an internal neighbour 701 return NULL;//error 702 k1=((long *)surrogate_neighbours->data)[k2]; 703 //the coordinates of the triangle are already (x,y). Get centroid of the neighbour (x1,y1) 704 coord_index=2*k1; 705 x1=((double *)centroid_coordinates->data)[coord_index]; 706 y1=((double *)centroid_coordinates->data)[coord_index+1]; 707 //compute x- and y- distances between the centroid of the FV triangle and that of its neighbour 708 dx1=x1-x; dy1=y1-y; 709 //set area2 as the square of the distance 710 area2=dx1*dx1+dy1*dy1; 711 //set dx2=(x1-x0)/((x1-x0)^2+(y1-y0)^2) and dy2=(y1-y0)/((x1-x0)^2+(y1-y0)^2) which 712 //respectively correspond to the x- and y- gradients of the conserved quantities 713 dx2=1.0/area2; 714 dy2=dx2*dy1; 715 dx2*=dx1; 716 717 //## stage ### 718 //compute differentials 719 dq1=((double *)stage_centroid_values->data)[k1]-((double *)stage_centroid_values->data)[k]; 720 //calculate the gradient between the centroid of the FV triangle and that of its neighbour 721 a=dq1*dx2; 722 b=dq1*dy2; 723 //calculate provisional vertex jumps, to be limited 724 dqv[0]=a*dxv0+b*dyv0; 725 dqv[1]=a*dxv1+b*dyv1; 726 dqv[2]=a*dxv2+b*dyv2; 727 //now limit the jumps 728 if (dq1>=0.0){ 729 qmin=0.0; 730 qmax=dq1; 731 } 732 else{ 733 qmin=dq1; 734 qmax=0.0; 735 } 736 limit_gradient(dqv,qmin,qmax,beta_w);//the gradient will be limited 737 for (i=0;i<3;i++) 738 ((double *)stage_vertex_values->data)[k3+i]=((double *)stage_centroid_values->data)[k]+dqv[i]; 739 740 //## xmom ### 741 //compute differentials 742 dq1=((double *)xmom_centroid_values->data)[k1]-((double *)xmom_centroid_values->data)[k]; 743 //calculate the gradient between the centroid of the FV triangle and that of its neighbour 744 a=dq1*dx2; 745 b=dq1*dy2; 746 //calculate provisional vertex jumps, to be limited 747 dqv[0]=a*dxv0+b*dyv0; 748 dqv[1]=a*dxv1+b*dyv1; 749 dqv[2]=a*dxv2+b*dyv2; 750 //now limit the jumps 751 if (dq1>=0.0){ 752 qmin=0.0; 753 qmax=dq1; 754 } 755 else{ 756 qmin=dq1; 757 qmax=0.0; 758 } 759 limit_gradient(dqv,qmin,qmax,beta_w);//the gradient will be limited 760 for (i=0;i<3;i++) 761 ((double *)xmom_vertex_values->data)[k3+i]=((double *)xmom_centroid_values->data)[k]+dqv[i]; 762 763 //## ymom ### 764 //compute differentials 765 dq1=((double *)ymom_centroid_values->data)[k1]-((double *)ymom_centroid_values->data)[k]; 766 //calculate the gradient between the centroid of the FV triangle and that of its neighbour 767 a=dq1*dx2; 768 b=dq1*dy2; 769 //calculate provisional vertex jumps, to be limited 770 dqv[0]=a*dxv0+b*dyv0; 771 dqv[1]=a*dxv1+b*dyv1; 772 dqv[2]=a*dxv2+b*dyv2; 773 //now limit the jumps 774 if (dq1>=0.0){ 775 qmin=0.0; 776 qmax=dq1; 777 } 778 else{ 779 qmin=dq1; 780 qmax=0.0; 781 } 782 limit_gradient(dqv,qmin,qmax,beta_w);//the gradient will be limited 783 for (i=0;i<3;i++) 784 ((double *)ymom_vertex_values->data)[k3+i]=((double *)ymom_centroid_values->data)[k]+dqv[i]; 785 }//else [number_of_boudaries==2] 786 }//for k=0 to number_of_elements-1 787 return Py_BuildValue(""); 788 }//extrapolate_second-order_sw 789 425 790 PyObject *rotate(PyObject *self, PyObject *args, PyObject *kwargs) { 426 791 // … … 480 845 } 481 846 482 483 847 PyObject *compute_fluxes(PyObject *self, PyObject *args) { 484 848 /*Compute all fluxes and the timestep suitable for all volumes … … 499 863 domain.timestep = compute_fluxes(timestep, 500 864 domain.epsilon, 501 865 domain.g, 502 866 domain.neighbours, 503 867 domain.neighbour_edges, … … 515 879 Stage.explicit_update, 516 880 Xmom.explicit_update, 517 Ymom.explicit_update) 881 Ymom.explicit_update, 882 already_computed_flux) 518 883 519 884 … … 537 902 *stage_explicit_update, 538 903 *xmom_explicit_update, 539 *ymom_explicit_update; 904 *ymom_explicit_update, 905 *already_computed_flux;//tracks whether the flux across an edge has already been computed 540 906 541 907 … … 543 909 double timestep, max_speed, epsilon, g; 544 910 double normal[2], ql[3], qr[3], zl, zr; 545 double flux[3], edgeflux[3]; //Work arrays for summing up fluxes 546 547 int number_of_elements, k, i, j, m, n; 548 int ki, nm, ki2; //Index shorthands 911 double edgeflux[3]; //Work arrays for summing up fluxes 912 913 int number_of_elements, k, i, m, n; 914 int ki, nm=0, ki2; //Index shorthands 915 static long call=1; 549 916 550 917 551 918 // Convert Python arguments to C 552 if (!PyArg_ParseTuple(args, "dddOOOOOOOOOOOOOOOO ",919 if (!PyArg_ParseTuple(args, "dddOOOOOOOOOOOOOOOOO", 553 920 ×tep, 554 921 &epsilon, … … 567 934 &stage_explicit_update, 568 935 &xmom_explicit_update, 569 &ymom_explicit_update)) { 936 &ymom_explicit_update, 937 &already_computed_flux)) { 570 938 PyErr_SetString(PyExc_RuntimeError, "Input arguments failed"); 571 939 return NULL; 572 940 } 573 574 941 number_of_elements = stage_edge_values -> dimensions[0]; 575 576 942 call++;//a static local variable to which already_computed_flux is compared 943 //set explicit_update to zero for all conserved_quantities. 944 //This assumes compute_fluxes called before forcing terms 577 945 for (k=0; k<number_of_elements; k++) { 578 579 //Reset work array 580 for (j=0; j<3; j++) flux[j] = 0.0; 581 582 //Loop through neighbours and compute edge flux for each 946 ((double *) stage_explicit_update -> data)[k]=0.0; 947 ((double *) xmom_explicit_update -> data)[k]=0.0; 948 ((double *) ymom_explicit_update -> data)[k]=0.0; 949 } 950 //Loop through neighbours and compute edge flux for each 951 for (k=0; k<number_of_elements; k++) { 583 952 for (i=0; i<3; i++) { 584 953 ki = k*3+i; 954 if (((long *) already_computed_flux->data)[ki]==call)//we've already computed the flux across this edge 955 continue; 585 956 ql[0] = ((double *) stage_edge_values -> data)[ki]; 586 957 ql[1] = ((double *) xmom_edge_values -> data)[ki]; … … 598 969 } else { 599 970 m = ((long *) neighbour_edges -> data)[ki]; 600 601 971 nm = n*3+m; 602 972 qr[0] = ((double *) stage_edge_values -> data)[nm]; … … 605 975 zr = ((double *) bed_edge_values -> data)[nm]; 606 976 } 607 608 //printf("%d %d [%d] (%d, %d): %.2f %.2f %.2f\n", k, i, ki, n, m,609 // ql[0], ql[1], ql[2]);610 611 612 977 // Outward pointing normal vector 613 978 // normal = domain.normals[k, 2*i:2*i+2] … … 615 980 normal[0] = ((double *) normals -> data)[ki2]; 616 981 normal[1] = ((double *) normals -> data)[ki2+1]; 617 618 982 //Edge flux computation 619 983 flux_function(ql, qr, zl, zr, … … 621 985 epsilon, g, 622 986 edgeflux, &max_speed); 623 624 625 //flux -= edgeflux * edgelengths[k,i] 626 for (j=0; j<3; j++) { 627 flux[j] -= edgeflux[j]*((double *) edgelengths -> data)[ki]; 987 //update triangle k 988 ((long *) already_computed_flux->data)[ki]=call; 989 ((double *) stage_explicit_update -> data)[k] -= edgeflux[0]*((double *) edgelengths -> data)[ki]; 990 ((double *) xmom_explicit_update -> data)[k] -= edgeflux[1]*((double *) edgelengths -> data)[ki]; 991 ((double *) ymom_explicit_update -> data)[k] -= edgeflux[2]*((double *) edgelengths -> data)[ki]; 992 //update the neighbour n 993 if (n>=0){ 994 ((long *) already_computed_flux->data)[nm]=call; 995 ((double *) stage_explicit_update -> data)[n] += edgeflux[0]*((double *) edgelengths -> data)[nm]; 996 ((double *) xmom_explicit_update -> data)[n] += edgeflux[1]*((double *) edgelengths -> data)[nm]; 997 ((double *) ymom_explicit_update -> data)[n] += edgeflux[2]*((double *) edgelengths -> data)[nm]; 628 998 } 629 630 //Update timestep 631 //timestep = min(timestep, domain.radii[k]/max_speed) 632 //FIXME: SR Add parameter for CFL condition 633 if (max_speed > epsilon) { 634 timestep = min(timestep, ((double *) radii -> data)[k]/max_speed); 635 } 999 ///for (j=0; j<3; j++) { 1000 ///flux[j] -= edgeflux[j]*((double *) edgelengths -> data)[ki]; 1001 ///} 1002 //Update timestep 1003 //timestep = min(timestep, domain.radii[k]/max_speed) 1004 //FIXME: SR Add parameter for CFL condition 1005 if (max_speed > epsilon) { 1006 timestep = min(timestep, ((double *) radii -> data)[k]/max_speed); 1007 //maxspeed in flux_function is calculated as max(|u+a|,|u-a|) 1008 if (n>=0) 1009 timestep = min(timestep, ((double *) radii -> data)[n]/max_speed); 1010 } 636 1011 } // end for i 637 638 1012 //Normalise by area and store for when all conserved 639 1013 //quantities get updated 640 // flux /= areas[k] 641 for (j=0; j<3; j++) { 642 flux[j] /= ((double *) areas -> data)[k]; 643 } 644 645 ((double *) stage_explicit_update -> data)[k] = flux[0]; 646 ((double *) xmom_explicit_update -> data)[k] = flux[1]; 647 ((double *) ymom_explicit_update -> data)[k] = flux[2]; 648 1014 ((double *) stage_explicit_update -> data)[k] /= ((double *) areas -> data)[k]; 1015 ((double *) xmom_explicit_update -> data)[k] /= ((double *) areas -> data)[k]; 1016 ((double *) ymom_explicit_update -> data)[k] /= ((double *) areas -> data)[k]; 649 1017 } //end for k 650 651 1018 return Py_BuildValue("d", timestep); 652 1019 } 653 654 655 1020 656 1021 PyObject *protect(PyObject *self, PyObject *args) { … … 812 1177 } 813 1178 814 815 1179 PyObject *h_limiter_sw(PyObject *self, PyObject *args) { 1180 //a faster version of h_limiter above 1181 PyObject *domain, *Tmp; 1182 PyArrayObject 1183 *hv, *hc, //Depth at vertices and centroids 1184 *hvbar, //Limited depth at vertices (return values) 1185 *neighbours; 1186 1187 int k, i, N, k3,k0,k1,k2; 1188 int dimensions[2]; 1189 double beta_h; //Safety factor (see config.py) 1190 double hmin, hmax, dh[3]; 1191 // Convert Python arguments to C 1192 if (!PyArg_ParseTuple(args, "OOO", &domain, &hc, &hv)) 1193 return NULL; 1194 neighbours = get_consecutive_array(domain, "neighbours"); 1195 1196 //Get safety factor beta_h 1197 Tmp = PyObject_GetAttrString(domain, "beta_h"); 1198 if (!Tmp) 1199 return NULL; 1200 beta_h = PyFloat_AsDouble(Tmp); 1201 1202 Py_DECREF(Tmp); 1203 1204 N = hc -> dimensions[0]; 1205 1206 //Create hvbar 1207 dimensions[0] = N; 1208 dimensions[1] = 3; 1209 hvbar = (PyArrayObject *) PyArray_FromDims(2, dimensions, PyArray_DOUBLE); 1210 for (k=0;k<N;k++){ 1211 k3=k*3; 1212 //get the ids of the neighbours 1213 k0 = ((long*) neighbours -> data)[k3]; 1214 k1 = ((long*) neighbours -> data)[k3+1]; 1215 k2 = ((long*) neighbours -> data)[k3+2]; 1216 //set hvbar provisionally 1217 for (i=0;i<3;i++){ 1218 ((double*) hvbar -> data)[k3+i] = ((double*) hv -> data)[k3+i]; 1219 dh[i]=((double*) hvbar -> data)[k3+i]-((double*) hc -> data)[k]; 1220 } 1221 hmin=((double*) hc -> data)[k]; 1222 hmax=hmin; 1223 if (k0>=0){ 1224 hmin=min(hmin,((double*) hc -> data)[k0]); 1225 hmax=max(hmax,((double*) hc -> data)[k0]); 1226 } 1227 if (k1>=0){ 1228 hmin=min(hmin,((double*) hc -> data)[k1]); 1229 hmax=max(hmax,((double*) hc -> data)[k1]); 1230 } 1231 if (k2>=0){ 1232 hmin=min(hmin,((double*) hc -> data)[k2]); 1233 hmax=max(hmax,((double*) hc -> data)[k2]); 1234 } 1235 hmin-=((double*) hc -> data)[k]; 1236 hmax-=((double*) hc -> data)[k]; 1237 limit_gradient(dh,hmin,hmax,beta_h); 1238 for (i=0;i<3;i++) 1239 ((double*) hvbar -> data)[k3+i] = ((double*) hc -> data)[k]+dh[i]; 1240 } 1241 return PyArray_Return(hvbar); 1242 } 816 1243 817 1244 PyObject *assign_windfield_values(PyObject *self, PyObject *args) { … … 864 1291 865 1292 {"rotate", (PyCFunction)rotate, METH_VARARGS | METH_KEYWORDS, "Print out"}, 1293 {"extrapolate_second_order_sw", extrapolate_second_order_sw, METH_VARARGS, "Print out"}, 866 1294 {"compute_fluxes", compute_fluxes, METH_VARARGS, "Print out"}, 867 1295 {"gravity", gravity, METH_VARARGS, "Print out"}, … … 870 1298 METH_VARARGS, "Print out"}, 871 1299 {"h_limiter", h_limiter, 1300 METH_VARARGS, "Print out"}, 1301 {"h_limiter_sw", h_limiter_sw, 872 1302 METH_VARARGS, "Print out"}, 873 1303 {"protect", protect, METH_VARARGS | METH_KEYWORDS, "Print out"},
Note: See TracChangeset
for help on using the changeset viewer.