Changeset 4886
- Timestamp:
- Dec 12, 2007, 5:38:37 PM (17 years ago)
- Location:
- anuga_core/source/anuga
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
anuga_core/source/anuga/abstract_2d_finite_volumes/quantity.py
r4883 r4886 229 229 #(either from this module or C-extension) 230 230 interpolate_from_vertices_to_edges(self) 231 232 def interpolate_from_edges_to_vertices(self): 233 #Call correct module function 234 #(either from this module or C-extension) 235 interpolate_from_edges_to_vertices(self) 231 236 232 237 … … 1400 1405 1401 1406 1402 ##def limit_by_vertex(self):1403 ###Call correct module function1404 ###(either from this module or C-extension)1405 ## limit_by_vertex()1406 1407 1408 ##def limit_by_edge(self):1409 ###Call correct module function1410 ###(either from this module or C-extension)1411 ## limit_by_edge()1407 def limit_by_vertex(self): 1408 #Call correct module function 1409 #(either from this module or C-extension) 1410 limit_by_vertex(self) 1411 1412 1413 def limit_by_edge(self): 1414 #Call correct module function 1415 #(either from this module or C-extension) 1416 limit_by_edge(self) 1412 1417 1413 1418 def extrapolate_second_order(self): … … 1439 1444 compute_gradients,\ 1440 1445 limit_old,\ 1446 limit_by_vertex,\ 1447 limit_by_edge,\ 1441 1448 extrapolate_second_order,\ 1442 1449 interpolate_from_vertices_to_edges,\ 1450 interpolate_from_edges_to_vertices,\ 1443 1451 update 1444 1452 else: -
anuga_core/source/anuga/abstract_2d_finite_volumes/quantity_ext.c
r4883 r4886 122 122 y2 = vertex_coordinates[k6 + 5]; 123 123 124 // Extrapolate 124 // Extrapolate to Vertices 125 125 vertex_values[k3+0] = centroid_values[k] + a[k]*(x0-x) + b[k]*(y0-y); 126 126 vertex_values[k3+1] = centroid_values[k] + a[k]*(x1-x) + b[k]*(y1-y); 127 127 vertex_values[k3+2] = centroid_values[k] + a[k]*(x2-x) + b[k]*(y2-y); 128 128 129 129 // Extrapolate to Edges (midpoints) 130 130 edge_values[k3+0] = 0.5*(vertex_values[k3 + 1]+vertex_values[k3 + 2]); 131 131 edge_values[k3+1] = 0.5*(vertex_values[k3 + 2]+vertex_values[k3 + 0]); … … 137 137 138 138 139 140 141 int _interpolate(int N, 139 int _limit_by_vertex(int N, double beta, 140 double* centroid_values, 141 double* vertex_values, 142 double* edge_values, 143 long* neighbours) { 144 145 int i, k, k2, k3, k6; 146 long n; 147 double qmin, qmax, qn, qc; 148 double dq, dqa[3], phi, r; 149 150 for (k=0; k<N; k++){ 151 k6 = 6*k; 152 k3 = 3*k; 153 k2 = 2*k; 154 155 qc = centroid_values[k]; 156 qmin = qc; 157 qmax = qc; 158 159 for (i=0; i<3; i++) { 160 n = neighbours[k3+i]; 161 if (n >= 0) { 162 qn = centroid_values[n]; //Neighbour's centroid value 163 164 qmin = min(qmin, qn); 165 qmax = max(qmax, qn); 166 } 167 } 168 169 phi = 1.0; 170 for (i=0; i<3; i++) { 171 r = 1.0; 172 173 dq = vertex_values[k3+i] - qc; //Delta between vertex and centroid values 174 dqa[i] = dq; //Save dq for use in updating vertex values 175 176 if (dq > 0.0) r = (qmax - qc)/dq; 177 if (dq < 0.0) r = (qmin - qc)/dq; 178 179 180 phi = min( min(r*beta, 1.0), phi); 181 } 182 183 //Update vertex and edge values using phi limiter 184 vertex_values[k3+0] = qc + phi*dqa[0]; 185 vertex_values[k3+1] = qc + phi*dqa[1]; 186 vertex_values[k3+2] = qc + phi*dqa[2]; 187 188 edge_values[k3+0] = 0.5*(vertex_values[k3+1] + vertex_values[k3+2]); 189 edge_values[k3+1] = 0.5*(vertex_values[k3+2] + vertex_values[k3+0]); 190 edge_values[k3+2] = 0.5*(vertex_values[k3+0] + vertex_values[k3+1]); 191 192 } 193 194 return 0; 195 } 196 197 int _limit_by_edge(int N, double beta, 198 double* centroid_values, 199 double* vertex_values, 200 double* edge_values, 201 long* neighbours) { 202 203 int i, k, k2, k3, k6; 204 long n; 205 double qmin, qmax, qn, qc; 206 double dq, dqa[3], phi, r; 207 208 for (k=0; k<N; k++){ 209 k6 = 6*k; 210 k3 = 3*k; 211 k2 = 2*k; 212 213 qc = centroid_values[k]; 214 qmin = qc; 215 qmax = qc; 216 217 for (i=0; i<3; i++) { 218 n = neighbours[k3+i]; 219 if (n >= 0) { 220 qn = centroid_values[n]; //Neighbour's centroid value 221 222 qmin = min(qmin, qn); 223 qmax = max(qmax, qn); 224 } 225 } 226 227 phi = 1.0; 228 for (i=0; i<3; i++) { 229 r = 1.0; 230 231 dq = edge_values[k3+i] - qc; //Delta between edge and centroid values 232 dqa[i] = dq; //Save dq for use in updating vertex values 233 234 if (dq > 0.0) r = (qmax - qc)/dq; 235 if (dq < 0.0) r = (qmin - qc)/dq; 236 237 238 phi = min( min(r*beta, 1.0), phi); 239 } 240 241 //Update vertex and edge values using phi limiter 242 edge_values[k3+0] = qc + phi*dqa[0]; 243 edge_values[k3+1] = qc + phi*dqa[1]; 244 edge_values[k3+2] = qc + phi*dqa[2]; 245 246 vertex_values[k3+0] = edge_values[k3+1] + edge_values[k3+2] - edge_values[k3+0]; 247 vertex_values[k3+1] = edge_values[k3+2] + edge_values[k3+0] - edge_values[k3+1]; 248 vertex_values[k3+2] = edge_values[k3+0] + edge_values[k3+1] - edge_values[k3+2]; 249 250 } 251 252 return 0; 253 } 254 255 256 257 int _interpolate_from_vertices_to_edges(int N, 142 258 double* vertex_values, 143 259 double* edge_values) { … … 157 273 edge_values[k3 + 1] = 0.5*(q0+q2); 158 274 edge_values[k3 + 2] = 0.5*(q0+q1); 275 } 276 return 0; 277 } 278 279 280 int _interpolate_from_edges_to_vertices(int N, 281 double* vertex_values, 282 double* edge_values) { 283 284 int k, k3; 285 double e0, e1, e2; 286 287 288 for (k=0; k<N; k++) { 289 k3 = 3*k; 290 291 e0 = edge_values[k3 + 0]; 292 e1 = edge_values[k3 + 1]; 293 e2 = edge_values[k3 + 2]; 294 295 vertex_values[k3 + 0] = e1 + e2 - e0; 296 vertex_values[k3 + 1] = e2 + e0 - e1; 297 vertex_values[k3 + 2] = e0 + e1 - e2; 159 298 } 160 299 return 0; … … 458 597 N = vertex_values -> dimensions[0]; 459 598 460 err = _interpolate(N, 599 err = _interpolate_from_vertices_to_edges(N, 600 (double*) vertex_values -> data, 601 (double*) edge_values -> data); 602 603 if (err != 0) { 604 PyErr_SetString(PyExc_RuntimeError, 605 "Interpolate could not be computed"); 606 return NULL; 607 } 608 609 // Release and return 610 Py_DECREF(vertex_values); 611 Py_DECREF(edge_values); 612 613 return Py_BuildValue(""); 614 } 615 616 617 PyObject *interpolate_from_edges_to_vertices(PyObject *self, PyObject *args) { 618 // 619 //Compute vertex values from edge values using linear interpolation 620 // 621 622 PyObject *quantity; 623 PyArrayObject *vertex_values, *edge_values; 624 625 int N, err; 626 627 // Convert Python arguments to C 628 if (!PyArg_ParseTuple(args, "O", &quantity)) { 629 PyErr_SetString(PyExc_RuntimeError, 630 "quantity_ext.c: interpolate_from_edges_to_vertices could not parse input"); 631 return NULL; 632 } 633 634 vertex_values = get_consecutive_array(quantity, "vertex_values"); 635 edge_values = get_consecutive_array(quantity, "edge_values"); 636 637 N = vertex_values -> dimensions[0]; 638 639 err = _interpolate_from_edges_to_vertices(N, 461 640 (double*) vertex_values -> data, 462 641 (double*) edge_values -> data); … … 795 974 796 975 976 PyObject *limit_by_vertex(PyObject *self, PyObject *args) { 977 //Limit slopes for each volume to eliminate artificial variance 978 //introduced by e.g. second order extrapolator 979 980 //This is an unsophisticated limiter as it does not take into 981 //account dependencies among quantities. 982 983 //precondition: 984 // vertex values are estimated from gradient 985 //postcondition: 986 // vertex and edge values are updated 987 // 988 989 PyObject *quantity, *domain, *Tmp; 990 PyArrayObject 991 *vertex_values, //Conserved quantities at vertices 992 *centroid_values, //Conserved quantities at centroids 993 *edge_values, //Conserved quantities at edges 994 *neighbours; 995 996 double beta_w; //Safety factor 997 int N, err; 998 999 1000 // Convert Python arguments to C 1001 if (!PyArg_ParseTuple(args, "O", &quantity)) { 1002 PyErr_SetString(PyExc_RuntimeError, 1003 "quantity_ext.c: limit_by_vertex could not parse input"); 1004 return NULL; 1005 } 1006 1007 domain = PyObject_GetAttrString(quantity, "domain"); 1008 if (!domain) { 1009 PyErr_SetString(PyExc_RuntimeError, 1010 "quantity_ext.c: limit_by_vertex could not obtain domain object from quantity"); 1011 1012 return NULL; 1013 } 1014 1015 // Get safety factor beta_w 1016 Tmp = PyObject_GetAttrString(domain, "beta_w"); 1017 if (!Tmp) { 1018 PyErr_SetString(PyExc_RuntimeError, 1019 "quantity_ext.c: limit_by_vertex could not obtain beta_w object from domain"); 1020 1021 return NULL; 1022 } 1023 1024 1025 // Get pertinent variables 1026 neighbours = get_consecutive_array(domain, "neighbours"); 1027 centroid_values = get_consecutive_array(quantity, "centroid_values"); 1028 vertex_values = get_consecutive_array(quantity, "vertex_values"); 1029 edge_values = get_consecutive_array(quantity, "edge_values"); 1030 beta_w = PyFloat_AsDouble(Tmp); 1031 1032 1033 N = centroid_values -> dimensions[0]; 1034 1035 err = _limit_by_vertex(N, beta_w, 1036 (double*) centroid_values -> data, 1037 (double*) vertex_values -> data, 1038 (double*) edge_values -> data, 1039 (long*) neighbours -> data); 1040 1041 if (err != 0) { 1042 PyErr_SetString(PyExc_RuntimeError, 1043 "Internal function _limit_by_vertex failed"); 1044 return NULL; 1045 } 1046 1047 1048 // Release 1049 Py_DECREF(neighbours); 1050 Py_DECREF(centroid_values); 1051 Py_DECREF(vertex_values); 1052 Py_DECREF(edge_values); 1053 Py_DECREF(Tmp); 1054 1055 1056 return Py_BuildValue(""); 1057 } 1058 1059 1060 1061 PyObject *limit_by_edge(PyObject *self, PyObject *args) { 1062 //Limit slopes for each volume to eliminate artificial variance 1063 //introduced by e.g. second order extrapolator 1064 1065 //This is an unsophisticated limiter as it does not take into 1066 //account dependencies among quantities. 1067 1068 //precondition: 1069 // vertex values are estimated from gradient 1070 //postcondition: 1071 // vertex and edge values are updated 1072 // 1073 1074 PyObject *quantity, *domain, *Tmp; 1075 PyArrayObject 1076 *vertex_values, //Conserved quantities at vertices 1077 *centroid_values, //Conserved quantities at centroids 1078 *edge_values, //Conserved quantities at edges 1079 *neighbours; 1080 1081 double beta_w; //Safety factor 1082 int N, err; 1083 1084 1085 // Convert Python arguments to C 1086 if (!PyArg_ParseTuple(args, "O", &quantity)) { 1087 PyErr_SetString(PyExc_RuntimeError, 1088 "quantity_ext.c: limit_by_edge could not parse input"); 1089 return NULL; 1090 } 1091 1092 domain = PyObject_GetAttrString(quantity, "domain"); 1093 if (!domain) { 1094 PyErr_SetString(PyExc_RuntimeError, 1095 "quantity_ext.c: limit_by_edge could not obtain domain object from quantity"); 1096 1097 return NULL; 1098 } 1099 1100 // Get safety factor beta_w 1101 Tmp = PyObject_GetAttrString(domain, "beta_w"); 1102 if (!Tmp) { 1103 PyErr_SetString(PyExc_RuntimeError, 1104 "quantity_ext.c: limit_by_edge could not obtain beta_w object from domain"); 1105 1106 return NULL; 1107 } 1108 1109 1110 // Get pertinent variables 1111 neighbours = get_consecutive_array(domain, "neighbours"); 1112 centroid_values = get_consecutive_array(quantity, "centroid_values"); 1113 vertex_values = get_consecutive_array(quantity, "vertex_values"); 1114 edge_values = get_consecutive_array(quantity, "edge_values"); 1115 beta_w = PyFloat_AsDouble(Tmp); 1116 1117 1118 N = centroid_values -> dimensions[0]; 1119 1120 err = _limit_by_edge(N, beta_w, 1121 (double*) centroid_values -> data, 1122 (double*) vertex_values -> data, 1123 (double*) edge_values -> data, 1124 (long*) neighbours -> data); 1125 1126 if (err != 0) { 1127 PyErr_SetString(PyExc_RuntimeError, 1128 "Internal function _limit_by_vertex failed"); 1129 return NULL; 1130 } 1131 1132 1133 // Release 1134 Py_DECREF(neighbours); 1135 Py_DECREF(centroid_values); 1136 Py_DECREF(vertex_values); 1137 Py_DECREF(edge_values); 1138 Py_DECREF(Tmp); 1139 1140 1141 return Py_BuildValue(""); 1142 } 1143 1144 797 1145 798 1146 // Method table for python module 799 1147 static struct PyMethodDef MethodTable[] = { 800 1148 {"limit_old", limit_old, METH_VARARGS, "Print out"}, 1149 {"limit_by_vertex", limit_by_vertex, METH_VARARGS, "Print out"}, 1150 {"limit_by_edge", limit_by_edge, METH_VARARGS, "Print out"}, 801 1151 {"update", update, METH_VARARGS, "Print out"}, 802 1152 {"backup_centroid_values", backup_centroid_values, METH_VARARGS, "Print out"}, … … 808 1158 interpolate_from_vertices_to_edges, 809 1159 METH_VARARGS, "Print out"}, 1160 {"interpolate_from_edges_to_vertices", 1161 interpolate_from_edges_to_vertices, 1162 METH_VARARGS, "Print out"}, 810 1163 {"average_vertex_values", average_vertex_values, METH_VARARGS, "Print out"}, 811 1164 {NULL, NULL, 0, NULL} // sentinel -
anuga_core/source/anuga/abstract_2d_finite_volumes/test_quantity.py
r4883 r4886 1445 1445 1446 1446 1447 def test_ limiter(self):1447 def test_vertex_limiter(self): 1448 1448 quantity = Conserved_quantity(self.mesh4) 1449 1449 … … 1453 1453 1454 1454 #Limit 1455 quantity.limit ()1455 quantity.limit_by_vertex() 1456 1456 1457 1457 #Assert that central triangle is limited by neighbours … … 1474 1474 1475 1475 1476 1477 def test_edge_limiter(self): 1478 quantity = Conserved_quantity(self.mesh4) 1479 1480 #Create a deliberate overshoot (e.g. from gradient computation) 1481 quantity.set_values([[3,0,3], [2,2,6], [5,3,8], [8,3,5]]) 1482 1483 1484 #Limit 1485 quantity.limit_by_edge() 1486 1487 #Assert that central triangle is limited by neighbours 1488 assert quantity.edge_values[1,0] <= quantity.centroid_values[2] 1489 assert quantity.edge_values[1,0] >= quantity.centroid_values[0] 1490 1491 assert quantity.edge_values[1,1] <= quantity.centroid_values[2] 1492 assert quantity.edge_values[1,1] >= quantity.centroid_values[0] 1493 1494 assert quantity.edge_values[1,2] <= quantity.centroid_values[2] 1495 assert quantity.edge_values[1,2] <= quantity.centroid_values[0] 1496 1497 1498 1499 #Assert that quantities are conserved 1500 from Numeric import sum 1501 for k in range(quantity.centroid_values.shape[0]): 1502 assert allclose (quantity.centroid_values[k], 1503 sum(quantity.vertex_values[k,:])/3) 1504 1505 1476 1506 def test_limiter2(self): 1477 1507 """Taken from test_shallow_water … … 1518 1548 1519 1549 1520 #Extrapolate 1550 #Extrapolate from centroid to vertices and edges 1521 1551 quantity.extrapolate_first_order() 1522 1552 1523 1553 #Interpolate 1524 quantity.interpolate_from_vertices_to_edges()1554 #quantity.interpolate_from_vertices_to_edges() 1525 1555 1526 1556 assert allclose(quantity.vertex_values, … … 1528 1558 assert allclose(quantity.edge_values, [[1,1,1], [2,2,2], 1529 1559 [3,3,3], [4, 4, 4]]) 1560 1561 1562 def test_interpolate_from_vertices_to_edges(self): 1563 quantity = Quantity(self.mesh4) 1564 1565 quantity.vertex_values = array([[1,0,2], [1,2,4], [4,2,5], [3,1,4]],Float) 1566 1567 quantity.interpolate_from_vertices_to_edges() 1568 1569 assert allclose(quantity.edge_values, [[1., 1.5, 0.5], 1570 [3., 2.5, 1.5], 1571 [3.5, 4.5, 3.], 1572 [2.5, 3.5, 2]]) 1573 1574 1575 def test_interpolate_from_edges_to_vertices(self): 1576 quantity = Quantity(self.mesh4) 1577 1578 quantity.edge_values = array([[1., 1.5, 0.5], 1579 [3., 2.5, 1.5], 1580 [3.5, 4.5, 3.], 1581 [2.5, 3.5, 2]],Float) 1582 1583 quantity.interpolate_from_edges_to_vertices() 1584 1585 assert allclose(quantity.vertex_values, 1586 [[1,0,2], [1,2,4], [4,2,5], [3,1,4]]) 1587 1530 1588 1531 1589 -
anuga_core/source/anuga/utilities/util_ext.h
r4883 r4886 166 166 167 167 168 void _limit_by_edge(int N, double beta, double* qc, double* qv,169 double* qmin, double* qmax) {170 171 //N are the number of elements172 int k, i, k3;173 double dq, dqa[3], phi, r;174 175 //printf("INSIDE\n");176 for (k=0; k<N; k++) {177 k3 = k*3;178 179 //Find the gradient limiter (phi) across vertices180 phi = 1.0;181 for (i=0; i<3; i++) {182 r = 1.0;183 184 dq = qv[k3+i] - qc[k]; //Delta between vertex and centroid values185 dqa[i] = dq; //Save dq for use in the next loop186 187 if (dq > 0.0) r = (qmax[k] - qc[k])/dq;188 if (dq < 0.0) r = (qmin[k] - qc[k])/dq;189 190 191 phi = min( min(r*beta, 1.0), phi);192 }193 194 //Then update using phi limiter195 for (i=0; i<3; i++) {196 qv[k3+i] = qc[k] + phi*dqa[i];197 }198 }199 }200 201 void _limit_by_vertex(int N, double beta, double* qc, double* qv,202 double* qmin, double* qmax) {203 204 //N are the number of elements205 int k, i, k3;206 double dq, dqa[3], phi, r;207 208 //printf("INSIDE\n");209 for (k=0; k<N; k++) {210 k3 = k*3;211 212 //Find the gradient limiter (phi) across vertices213 phi = 1.0;214 for (i=0; i<3; i++) {215 r = 1.0;216 217 dq = qv[k3+i] - qc[k]; //Delta between vertex and centroid values218 dqa[i] = dq; //Save dq for use in the next loop219 220 if (dq > 0.0) r = (qmax[k] - qc[k])/dq;221 if (dq < 0.0) r = (qmin[k] - qc[k])/dq;222 223 224 phi = min( min(r*beta, 1.0), phi);225 }226 227 //Then update using phi limiter228 for (i=0; i<3; i++) {229 qv[k3+i] = qc[k] + phi*dqa[i];230 }231 }232 }233 168 234 169
Note: See TracChangeset
for help on using the changeset viewer.