MFEM v2.0
|
00001 // Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at 00002 // the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights 00003 // reserved. See file COPYRIGHT for details. 00004 // 00005 // This file is part of the MFEM library. For more information and source code 00006 // availability see http://mfem.googlecode.com. 00007 // 00008 // MFEM is free software; you can redistribute it and/or modify it under the 00009 // terms of the GNU Lesser General Public License (as published by the Free 00010 // Software Foundation) version 2.1 dated February 1999. 00011 00012 // Implementation of GridFunction 00013 00014 #include "fem.hpp" 00015 #include <cstring> 00016 #include <math.h> 00017 00018 GridFunction::GridFunction(Mesh *m, istream &input) 00019 : Vector() 00020 { 00021 const int bufflen = 256; 00022 char buff[bufflen]; 00023 int vdim; 00024 00025 input >> ws; 00026 input.getline(buff, bufflen); // 'FiniteElementSpace' 00027 if (strcmp(buff, "FiniteElementSpace")) 00028 mfem_error("GridFunction::GridFunction():" 00029 " input stream is not a GridFunction!"); 00030 input.getline(buff, bufflen, ' '); // 'FiniteElementCollection:' 00031 input >> ws; 00032 input.getline(buff, bufflen); 00033 fec = FiniteElementCollection::New(buff); 00034 input.getline(buff, bufflen, ' '); // 'VDim:' 00035 input >> vdim; 00036 input.getline(buff, bufflen, ' '); // 'Ordering:' 00037 int ordering; 00038 input >> ordering; 00039 input.getline(buff, bufflen); // read the empty line 00040 fes = new FiniteElementSpace(m, fec, vdim, ordering); 00041 Vector::Load(input, fes->GetVSize()); 00042 } 00043 00044 GridFunction::GridFunction(Mesh *m, GridFunction *gf_array[], int num_pieces) 00045 { 00046 // all GridFunctions must have the same FE collection, vdim, ordering 00047 int vdim, ordering; 00048 00049 fes = gf_array[0]->FESpace(); 00050 fec = FiniteElementCollection::New(fes->FEColl()->Name()); 00051 vdim = fes->GetVDim(); 00052 ordering = fes->GetOrdering(); 00053 fes = new FiniteElementSpace(m, fec, vdim, ordering); 00054 SetSize(fes->GetVSize()); 00055 00056 if (m->NURBSext) 00057 { 00058 m->NURBSext->MergeGridFunctions(gf_array, num_pieces, *this); 00059 return; 00060 } 00061 00062 int g_ndofs = fes->GetNDofs(); 00063 int g_nvdofs = fes->GetNVDofs(); 00064 int g_nedofs = fes->GetNEDofs(); 00065 int g_nfdofs = fes->GetNFDofs(); 00066 int g_nddofs = g_ndofs - (g_nvdofs + g_nedofs + g_nfdofs); 00067 int vi, ei, fi, di; 00068 vi = ei = fi = di = 0; 00069 for (int i = 0; i < num_pieces; i++) 00070 { 00071 FiniteElementSpace *l_fes = gf_array[i]->FESpace(); 00072 int l_ndofs = l_fes->GetNDofs(); 00073 int l_nvdofs = l_fes->GetNVDofs(); 00074 int l_nedofs = l_fes->GetNEDofs(); 00075 int l_nfdofs = l_fes->GetNFDofs(); 00076 int l_nddofs = l_ndofs - (l_nvdofs + l_nedofs + l_nfdofs); 00077 const double *l_data = gf_array[i]->GetData(); 00078 double *g_data = data; 00079 if (ordering == Ordering::byNODES) 00080 { 00081 for (int d = 0; d < vdim; d++) 00082 { 00083 memcpy(g_data+vi, l_data, l_nvdofs*sizeof(double)); 00084 l_data += l_nvdofs; 00085 g_data += g_nvdofs; 00086 memcpy(g_data+ei, l_data, l_nedofs*sizeof(double)); 00087 l_data += l_nedofs; 00088 g_data += g_nedofs; 00089 memcpy(g_data+fi, l_data, l_nfdofs*sizeof(double)); 00090 l_data += l_nfdofs; 00091 g_data += g_nfdofs; 00092 memcpy(g_data+di, l_data, l_nddofs*sizeof(double)); 00093 l_data += l_nddofs; 00094 g_data += g_nddofs; 00095 } 00096 } 00097 else 00098 { 00099 memcpy(g_data+vdim*vi, l_data, vdim*l_nvdofs*sizeof(double)); 00100 l_data += vdim*l_nvdofs; 00101 g_data += vdim*g_nvdofs; 00102 memcpy(g_data+vdim*ei, l_data, vdim*l_nedofs*sizeof(double)); 00103 l_data += vdim*l_nedofs; 00104 g_data += vdim*g_nedofs; 00105 memcpy(g_data+vdim*fi, l_data, vdim*l_nfdofs*sizeof(double)); 00106 l_data += vdim*l_nfdofs; 00107 g_data += vdim*g_nfdofs; 00108 memcpy(g_data+vdim*di, l_data, vdim*l_nddofs*sizeof(double)); 00109 l_data += vdim*l_nddofs; 00110 g_data += vdim*g_nddofs; 00111 } 00112 vi += l_nvdofs; 00113 ei += l_nedofs; 00114 fi += l_nfdofs; 00115 di += l_nddofs; 00116 } 00117 } 00118 00119 GridFunction::~GridFunction() 00120 { 00121 if (fec) 00122 { 00123 delete fes; 00124 delete fec; 00125 } 00126 } 00127 00128 void GridFunction::Update(FiniteElementSpace *f) 00129 { 00130 if (fec) 00131 { 00132 delete fes; 00133 delete fec; 00134 fec = NULL; 00135 } 00136 fes = f; 00137 SetSize(fes->GetVSize()); 00138 } 00139 00140 void GridFunction::Update(FiniteElementSpace *f, Vector &v, int v_offset) 00141 { 00142 if (fec) 00143 { 00144 delete fes; 00145 delete fec; 00146 fec = NULL; 00147 } 00148 fes = f; 00149 SetDataAndSize((double *)v + v_offset, fes->GetVSize()); 00150 } 00151 00152 int GridFunction::VectorDim() const 00153 { 00154 const FiniteElement *fe = fes->GetFE(0); 00155 00156 if (fe->GetRangeType() == FiniteElement::SCALAR) 00157 return fes->GetVDim(); 00158 return fe->GetDim(); 00159 } 00160 00161 void GridFunction::GetNodalValues(int i, Array<double> &nval, int vdim) const 00162 { 00163 Array<int> vdofs; 00164 00165 int k; 00166 00167 fes->GetElementVDofs(i, vdofs); 00168 const FiniteElement *FElem = fes->GetFE(i); 00169 const IntegrationRule *ElemVert = 00170 Geometries.GetVertices(FElem->GetGeomType()); 00171 int dof = FElem->GetDof(); 00172 int n = ElemVert->GetNPoints(); 00173 nval.SetSize(n); 00174 vdim--; 00175 Vector loc_data; 00176 GetSubVector(vdofs, loc_data); 00177 00178 if (FElem->GetRangeType() == FiniteElement::SCALAR) 00179 { 00180 Vector shape(dof); 00181 for (k = 0; k < n; k++) 00182 { 00183 FElem->CalcShape(ElemVert->IntPoint(k), shape); 00184 nval[k] = shape * ((const double *)loc_data + dof * vdim); 00185 } 00186 } 00187 else 00188 { 00189 ElementTransformation *Tr = fes->GetElementTransformation(i); 00190 DenseMatrix vshape(dof, FElem->GetDim()); 00191 for (k = 0; k < n; k++) 00192 { 00193 Tr->SetIntPoint(&ElemVert->IntPoint(k)); 00194 FElem->CalcVShape(*Tr, vshape); 00195 nval[k] = loc_data * (&vshape(0,vdim)); 00196 } 00197 } 00198 } 00199 00200 00201 double GridFunction::GetValue(int i, const IntegrationPoint &ip, int vdim) 00202 const 00203 { 00204 Array<int> dofs; 00205 fes->GetElementDofs(i, dofs); 00206 fes->DofsToVDofs(vdim-1, dofs); 00207 Vector DofVal(dofs.Size()), LocVec; 00208 fes->GetFE(i)->CalcShape(ip, DofVal); 00209 GetSubVector(dofs, LocVec); 00210 00211 return (DofVal * LocVec); 00212 } 00213 00214 void GridFunction::GetVectorValue(int i, const IntegrationPoint &ip, 00215 Vector &val) const 00216 { 00217 const FiniteElement *FElem = fes->GetFE(i); 00218 int dof = FElem->GetDof(); 00219 Array<int> vdofs; 00220 fes->GetElementVDofs(i, vdofs); 00221 Vector loc_data; 00222 GetSubVector(vdofs, loc_data); 00223 if (FElem->GetRangeType() == FiniteElement::SCALAR) 00224 { 00225 Vector shape(dof); 00226 FElem->CalcShape(ip, shape); 00227 int vdim = fes->GetVDim(); 00228 val.SetSize(vdim); 00229 for (int k = 0; k < vdim; k++) 00230 { 00231 val(k) = shape * ((const double *)loc_data + dof * k); 00232 } 00233 } 00234 else 00235 { 00236 int dim = FElem->GetDim(); 00237 DenseMatrix vshape(dof, dim); 00238 ElementTransformation *Tr = fes->GetElementTransformation(i); 00239 Tr->SetIntPoint(&ip); 00240 FElem->CalcVShape(*Tr, vshape); 00241 val.SetSize(dim); 00242 vshape.MultTranspose(loc_data, val); 00243 } 00244 } 00245 00246 void GridFunction::GetValues(int i, const IntegrationRule &ir, Vector &vals, 00247 DenseMatrix &tr, int vdim) 00248 const 00249 { 00250 Array<int> dofs; 00251 00252 int k, n; 00253 00254 n = ir.GetNPoints(); 00255 vals.SetSize(n); 00256 fes->GetElementVDofs(i, dofs); 00257 const FiniteElement *FElem = fes->GetFE(i); 00258 ElementTransformation *ET; 00259 ET = fes->GetElementTransformation(i); 00260 ET->Transform(ir, tr); 00261 int dof = FElem->GetDof(); 00262 Vector DofVal(dof); 00263 vdim--; 00264 for (k = 0; k < n; k++) 00265 { 00266 FElem->CalcShape(ir.IntPoint(k), DofVal); 00267 vals(k) = 0.0; 00268 for (int j = 0; j < dof; j++) 00269 if (dofs[dof*vdim+j] >= 0) 00270 vals(k) += DofVal(j) * data[dofs[dof*vdim+j]]; 00271 else 00272 vals(k) -= DofVal(j) * data[-1-dofs[dof*vdim+j]]; 00273 } 00274 } 00275 00276 int GridFunction::GetFaceValues(int i, int side, const IntegrationRule &ir, 00277 Vector &vals, DenseMatrix &tr, 00278 int vdim) const 00279 { 00280 int n, di; 00281 FaceElementTransformations *Transf; 00282 00283 n = ir.GetNPoints(); 00284 IntegrationRule eir(n); // --- 00285 Transf = fes->GetMesh()->GetFaceElementTransformations(i, 0); 00286 if (side == 2) 00287 { 00288 if (Transf->Elem2No < 0 || 00289 fes->GetAttribute(Transf->Elem1No) <= 00290 fes->GetAttribute(Transf->Elem2No)) 00291 di = 0; 00292 else 00293 di = 1; 00294 } 00295 else 00296 di = side; 00297 if (di == 0) 00298 { 00299 Transf = fes->GetMesh()->GetFaceElementTransformations(i, 4); 00300 Transf->Loc1.Transform(ir, eir); 00301 GetValues(Transf->Elem1No, eir, vals, tr, vdim); 00302 } 00303 else 00304 { 00305 Transf = fes->GetMesh()->GetFaceElementTransformations(i, 8); 00306 Transf->Loc2.Transform(ir, eir); 00307 GetValues(Transf->Elem2No, eir, vals, tr, vdim); 00308 } 00309 00310 return di; 00311 } 00312 00313 void GridFunction::GetVectorValues(int i, const IntegrationRule &ir, 00314 DenseMatrix &vals, DenseMatrix &tr) 00315 const 00316 { 00317 const FiniteElement *FElem = fes->GetFE(i); 00318 int dof = FElem->GetDof(); 00319 Array<int> vdofs; 00320 fes->GetElementVDofs(i, vdofs); 00321 Vector loc_data; 00322 GetSubVector(vdofs, loc_data); 00323 int nip = ir.GetNPoints(); 00324 ElementTransformation *Tr = fes->GetElementTransformation(i); 00325 Tr->Transform(ir, tr); 00326 if (FElem->GetRangeType() == FiniteElement::SCALAR) 00327 { 00328 Vector shape(dof); 00329 int vdim = fes->GetVDim(); 00330 vals.SetSize(vdim, nip); 00331 for (int j = 0; j < nip; j++) 00332 { 00333 const IntegrationPoint &ip = ir.IntPoint(j); 00334 FElem->CalcShape(ip, shape); 00335 for (int k = 0; k < vdim; k++) 00336 { 00337 vals(k,j) = shape * ((const double *)loc_data + dof * k); 00338 } 00339 } 00340 } 00341 else 00342 { 00343 int dim = FElem->GetDim(); 00344 DenseMatrix vshape(dof, dim); 00345 vals.SetSize(dim, nip); 00346 Vector val_j; 00347 for (int j = 0; j < nip; j++) 00348 { 00349 const IntegrationPoint &ip = ir.IntPoint(j); 00350 Tr->SetIntPoint(&ip); 00351 FElem->CalcVShape(*Tr, vshape); 00352 vals.GetColumnReference(j, val_j); 00353 vshape.MultTranspose(loc_data, val_j); 00354 } 00355 } 00356 } 00357 00358 int GridFunction::GetFaceVectorValues( 00359 int i, int side, const IntegrationRule &ir, 00360 DenseMatrix &vals, DenseMatrix &tr) const 00361 { 00362 int n, di; 00363 FaceElementTransformations *Transf; 00364 00365 n = ir.GetNPoints(); 00366 IntegrationRule eir(n); // --- 00367 Transf = fes->GetMesh()->GetFaceElementTransformations(i, 0); 00368 if (side == 2) 00369 { 00370 if (Transf->Elem2No < 0 || 00371 fes->GetAttribute(Transf->Elem1No) <= 00372 fes->GetAttribute(Transf->Elem2No)) 00373 di = 0; 00374 else 00375 di = 1; 00376 } 00377 else 00378 di = side; 00379 if (di == 0) 00380 { 00381 Transf = fes->GetMesh()->GetFaceElementTransformations(i, 4); 00382 Transf->Loc1.Transform(ir, eir); 00383 GetVectorValues(Transf->Elem1No, eir, vals, tr); 00384 } 00385 else 00386 { 00387 Transf = fes->GetMesh()->GetFaceElementTransformations(i, 8); 00388 Transf->Loc2.Transform(ir, eir); 00389 GetVectorValues(Transf->Elem2No, eir, vals, tr); 00390 } 00391 00392 return di; 00393 } 00394 00395 void GridFunction::GetValuesFrom(GridFunction &orig_func) 00396 { 00397 // Without averaging ... 00398 00399 FiniteElementSpace *orig_fes = orig_func.FESpace(); 00400 Array<int> vdofs, orig_vdofs; 00401 Vector shape, loc_values, orig_loc_values; 00402 int i, j, d, ne, dof, odof, vdim; 00403 00404 ne = fes->GetNE(); 00405 vdim = fes->GetVDim(); 00406 for (i = 0; i < ne; i++) 00407 { 00408 fes->GetElementVDofs(i, vdofs); 00409 orig_fes->GetElementVDofs(i, orig_vdofs); 00410 orig_func.GetSubVector(orig_vdofs, orig_loc_values); 00411 const FiniteElement *fe = fes->GetFE(i); 00412 const FiniteElement *orig_fe = orig_fes->GetFE(i); 00413 dof = fe->GetDof(); 00414 odof = orig_fe->GetDof(); 00415 loc_values.SetSize(dof * vdim); 00416 shape.SetSize(odof); 00417 const IntegrationRule &ir = fe->GetNodes(); 00418 for (j = 0; j < dof; j++) 00419 { 00420 const IntegrationPoint &ip = ir.IntPoint(j); 00421 orig_fe->CalcShape(ip, shape); 00422 for (d = 0; d < vdim; d++) 00423 { 00424 loc_values(d*dof+j) = 00425 shape * ((const double *)orig_loc_values + d * odof) ; 00426 } 00427 } 00428 SetSubVector(vdofs, loc_values); 00429 } 00430 } 00431 00432 void GridFunction::GetBdrValuesFrom(GridFunction &orig_func) 00433 { 00434 // Without averaging ... 00435 00436 FiniteElementSpace *orig_fes = orig_func.FESpace(); 00437 Array<int> vdofs, orig_vdofs; 00438 Vector shape, loc_values, orig_loc_values; 00439 int i, j, d, nbe, dof, odof, vdim; 00440 00441 nbe = fes->GetNBE(); 00442 vdim = fes->GetVDim(); 00443 for (i = 0; i < nbe; i++) 00444 { 00445 fes->GetBdrElementVDofs(i, vdofs); 00446 orig_fes->GetBdrElementVDofs(i, orig_vdofs); 00447 orig_func.GetSubVector(orig_vdofs, orig_loc_values); 00448 const FiniteElement *fe = fes->GetBE(i); 00449 const FiniteElement *orig_fe = orig_fes->GetBE(i); 00450 dof = fe->GetDof(); 00451 odof = orig_fe->GetDof(); 00452 loc_values.SetSize(dof * vdim); 00453 shape.SetSize(odof); 00454 const IntegrationRule &ir = fe->GetNodes(); 00455 for (j = 0; j < dof; j++) 00456 { 00457 const IntegrationPoint &ip = ir.IntPoint(j); 00458 orig_fe->CalcShape(ip, shape); 00459 for (d = 0; d < vdim; d++) 00460 { 00461 loc_values(d*dof+j) = 00462 shape * ((const double *)orig_loc_values + d * odof); 00463 } 00464 } 00465 SetSubVector(vdofs, loc_values); 00466 } 00467 } 00468 00469 void GridFunction::GetVectorFieldValues( 00470 int i, const IntegrationRule &ir, DenseMatrix &vals, 00471 DenseMatrix &tr, int comp) const 00472 { 00473 Array<int> vdofs; 00474 ElementTransformation *transf; 00475 00476 int d, j, k, n, dim, dof, ind; 00477 00478 n = ir.GetNPoints(); 00479 fes->GetElementVDofs(i, vdofs); 00480 const FiniteElement *fe = fes->GetFE(i); 00481 dof = fe->GetDof(); 00482 dim = fe->GetDim(); 00483 int *dofs = &vdofs[comp*dof]; 00484 transf = fes->GetElementTransformation(i); 00485 transf->Transform(ir, tr); 00486 vals.SetSize(n, dim); 00487 DenseMatrix vshape(dof, dim); 00488 double a; 00489 for (k = 0; k < n; k++) 00490 { 00491 const IntegrationPoint &ip = ir.IntPoint(k); 00492 transf->SetIntPoint(&ip); 00493 fe->CalcVShape(*transf, vshape); 00494 for (d = 0; d < dim; d++) 00495 { 00496 a = 0.0; 00497 for (j = 0; j < dof; j++) 00498 if ( (ind=dofs[j]) >= 0 ) 00499 a += vshape(j, d) * data[ind]; 00500 else 00501 a -= vshape(j, d) * data[-1-ind]; 00502 vals(k, d) = a; 00503 } 00504 } 00505 } 00506 00507 void GridFunction::ReorderByNodes() 00508 { 00509 if (fes->GetOrdering() == Ordering::byNODES) 00510 return; 00511 00512 int i, j, k; 00513 int vdim = fes->GetVDim(); 00514 int ndofs = fes->GetNDofs(); 00515 double *temp = new double[size]; 00516 00517 k = 0; 00518 for (j = 0; j < ndofs; j++) 00519 for (i = 0; i < vdim; i++) 00520 temp[j+i*ndofs] = data[k++]; 00521 00522 for (i = 0; i < size; i++) 00523 data[i] = temp[i]; 00524 00525 delete [] temp; 00526 } 00527 00528 void GridFunction::GetVectorFieldNodalValues(Vector &val, int comp) const 00529 { 00530 int i, k; 00531 Array<int> overlap(fes->GetNV()); 00532 Array<int> vertices; 00533 DenseMatrix vals, tr; 00534 00535 val.SetSize(overlap.Size()); 00536 overlap = 0; 00537 val = 0.0; 00538 00539 comp--; 00540 for (i = 0; i < fes->GetNE(); i++) 00541 { 00542 const IntegrationRule *ir = 00543 Geometries.GetVertices(fes->GetFE(i)->GetGeomType()); 00544 fes->GetElementVertices(i, vertices); 00545 GetVectorFieldValues(i, *ir, vals, tr); 00546 for (k = 0; k < ir->GetNPoints(); k++) 00547 { 00548 val(vertices[k]) += vals(k, comp); 00549 overlap[vertices[k]]++; 00550 } 00551 } 00552 00553 for (i = 0; i < overlap.Size(); i++) 00554 val(i) /= overlap[i]; 00555 } 00556 00557 void GridFunction::ProjectVectorFieldOn(GridFunction &vec_field, int comp) 00558 { 00559 FiniteElementSpace *new_fes = vec_field.FESpace(); 00560 00561 int d, i, k, ind, dof; 00562 Array<int> overlap(new_fes->GetVSize()); 00563 Array<int> new_vdofs; 00564 DenseMatrix vals, tr; 00565 00566 overlap = 0; 00567 vec_field = 0.0; 00568 00569 for (i = 0; i < new_fes->GetNE(); i++) 00570 { 00571 const FiniteElement *fe = new_fes->GetFE(i); 00572 const IntegrationRule &ir = fe->GetNodes(); 00573 GetVectorFieldValues(i, ir, vals, tr, comp); 00574 new_fes->GetElementVDofs(i, new_vdofs); 00575 dof = fe->GetDof(); 00576 for (d = 0; d < fe->GetDim(); d++) 00577 for (k = 0; k < dof; k++) 00578 { 00579 if ( (ind=new_vdofs[dof*d+k]) < 0 ) 00580 ind = -1-ind, vals(k, d) = - vals(k, d); 00581 vec_field(ind) += vals(k, d); 00582 overlap[ind]++; 00583 } 00584 } 00585 00586 for (i = 0; i < overlap.Size(); i++) 00587 vec_field(i) /= overlap[i]; 00588 } 00589 00590 void GridFunction::GetDerivative(int comp, int der_comp, GridFunction &der) 00591 { 00592 FiniteElementSpace * der_fes = der.FESpace(); 00593 ElementTransformation * transf; 00594 Array<int> overlap(der_fes->GetVSize()); 00595 Array<int> der_dofs, vdofs; 00596 DenseMatrix dshape, inv_jac; 00597 Vector pt_grad, loc_func; 00598 int i, j, k, dim, dof, der_dof, ind; 00599 double a; 00600 00601 for (i = 0; i < overlap.Size(); i++) 00602 overlap[i] = 0; 00603 der = 0.0; 00604 00605 comp--; 00606 for (i = 0; i < der_fes->GetNE(); i++) 00607 { 00608 const FiniteElement *der_fe = der_fes->GetFE(i); 00609 const FiniteElement *fe = fes->GetFE(i); 00610 const IntegrationRule &ir = der_fe->GetNodes(); 00611 der_fes->GetElementDofs(i, der_dofs); 00612 fes->GetElementVDofs(i, vdofs); 00613 dim = fe->GetDim(); 00614 dof = fe->GetDof(); 00615 der_dof = der_fe->GetDof(); 00616 dshape.SetSize(dof, dim); 00617 inv_jac.SetSize(dim); 00618 pt_grad.SetSize(dim); 00619 loc_func.SetSize(dof); 00620 transf = fes->GetElementTransformation(i); 00621 for (j = 0; j < dof; j++) 00622 loc_func(j) = ( (ind=vdofs[comp*dof+j]) >= 0 ) ? 00623 (data[ind]) : (-data[-1-ind]); 00624 for (k = 0; k < der_dof; k++) 00625 { 00626 const IntegrationPoint &ip = ir.IntPoint(k); 00627 fe->CalcDShape(ip, dshape); 00628 dshape.MultTranspose(loc_func, pt_grad); 00629 transf->SetIntPoint(&ip); 00630 CalcInverse(transf->Jacobian(), inv_jac); 00631 a = 0.0; 00632 for (j = 0; j < dim; j++) 00633 a += inv_jac(j, der_comp) * pt_grad(j); 00634 der(der_dofs[k]) += a; 00635 overlap[der_dofs[k]]++; 00636 } 00637 } 00638 00639 for (i = 0; i < overlap.Size(); i++) 00640 der(i) /= overlap[i]; 00641 } 00642 00643 00644 void GridFunction::GetVectorGradientHat( 00645 ElementTransformation &T, DenseMatrix &gh) 00646 { 00647 int elNo = T.ElementNo; 00648 const FiniteElement *FElem = fes->GetFE(elNo); 00649 int dim = FElem->GetDim(), dof = FElem->GetDof(); 00650 Array<int> vdofs; 00651 fes->GetElementVDofs(elNo, vdofs); 00652 Vector loc_data; 00653 GetSubVector(vdofs, loc_data); 00654 // assuming scalar FE 00655 DenseMatrix dshape(dof, dim); 00656 FElem->CalcDShape(T.GetIntPoint(), dshape); 00657 gh.SetSize(dim); 00658 for (int i = 0; i < dim; i++) 00659 for (int j = 0; j < dim; j++) 00660 { 00661 double gij = 0.0; 00662 for (int k = 0; k < dof; k++) 00663 gij += loc_data(i * dof + k) * dshape(k, j); 00664 gh(i, j) = gij; 00665 } 00666 } 00667 00668 double GridFunction::GetDivergence(ElementTransformation &tr) 00669 { 00670 double div_v; 00671 int elNo = tr.ElementNo; 00672 const FiniteElement *FElem = fes->GetFE(elNo); 00673 if (FElem->GetRangeType() == FiniteElement::SCALAR) 00674 { 00675 DenseMatrix grad_hat; 00676 GetVectorGradientHat(tr, grad_hat); 00677 int dim = grad_hat.Size(); 00678 DenseMatrix Jinv(dim); 00679 CalcInverse(tr.Jacobian(), Jinv); 00680 div_v = 0.0; 00681 for (int i = 0; i < dim; i++) 00682 for (int j = 0; j < dim; j++) 00683 div_v += grad_hat(i, j) * Jinv(j, i); 00684 } 00685 else 00686 { 00687 // Assuming RT-type space 00688 Array<int> dofs; 00689 fes->GetElementDofs(elNo, dofs); 00690 Vector loc_data, divshape(FElem->GetDof()); 00691 GetSubVector(dofs, loc_data); 00692 FElem->CalcDivShape(tr.GetIntPoint(), divshape); 00693 div_v = (loc_data * divshape) / tr.Weight(); 00694 } 00695 return div_v; 00696 } 00697 00698 void GridFunction::GetGradient(ElementTransformation &tr, Vector &grad) 00699 { 00700 mfem_error("GridFunction::GetGradient(...) is not implemented!"); 00701 } 00702 00703 void GridFunction::GetGradients(const int elem, const IntegrationRule &ir, 00704 DenseMatrix &grad) 00705 { 00706 const FiniteElement *fe = fes->GetFE(elem); 00707 ElementTransformation *Tr = fes->GetElementTransformation(elem); 00708 DenseMatrix dshape(fe->GetDof(), fe->GetDim()); 00709 DenseMatrix Jinv(fe->GetDim()); 00710 Vector lval, gh(fe->GetDim()), gcol; 00711 Array<int> dofs; 00712 fes->GetElementDofs(elem, dofs); 00713 GetSubVector(dofs, lval); 00714 grad.SetSize(fe->GetDim(), ir.GetNPoints()); 00715 for (int i = 0; i < ir.GetNPoints(); i++) 00716 { 00717 const IntegrationPoint &ip = ir.IntPoint(i); 00718 fe->CalcDShape(ip, dshape); 00719 dshape.MultTranspose(lval, gh); 00720 Tr->SetIntPoint(&ip); 00721 grad.GetColumnReference(i, gcol); 00722 CalcInverse(Tr->Jacobian(), Jinv); 00723 Jinv.MultTranspose(gh, gcol); 00724 } 00725 } 00726 00727 void GridFunction::GetVectorGradient( 00728 ElementTransformation &tr, DenseMatrix &grad) 00729 { 00730 DenseMatrix grad_hat; 00731 GetVectorGradientHat(tr, grad_hat); 00732 DenseMatrix Jinv(grad_hat.Size()); 00733 CalcInverse(tr.Jacobian(), Jinv); 00734 grad.SetSize(grad_hat.Size()); 00735 Mult(grad_hat, Jinv, grad); 00736 } 00737 00738 void GridFunction::GetElementAverages(GridFunction &avgs) 00739 { 00740 MassIntegrator Mi; 00741 DenseMatrix loc_mass; 00742 Array<int> te_dofs, tr_dofs; 00743 Vector loc_avgs, loc_this; 00744 Vector int_psi(avgs.Size()); 00745 00746 avgs = 0.0; 00747 int_psi = 0.0; 00748 for (int i = 0; i < fes->GetNE(); i++) 00749 { 00750 Mi.AssembleElementMatrix2(*fes->GetFE(i), *avgs.FESpace()->GetFE(i), 00751 *fes->GetElementTransformation(i), loc_mass); 00752 fes->GetElementDofs(i, tr_dofs); 00753 avgs.FESpace()->GetElementDofs(i, te_dofs); 00754 GetSubVector(tr_dofs, loc_this); 00755 loc_avgs.SetSize(te_dofs.Size()); 00756 loc_mass.Mult(loc_this, loc_avgs); 00757 avgs.AddElementVector(te_dofs, loc_avgs); 00758 loc_this = 1.0; // assume the local basis for 'this' sums to 1 00759 loc_mass.Mult(loc_this, loc_avgs); 00760 int_psi.AddElementVector(te_dofs, loc_avgs); 00761 } 00762 for (int i = 0; i < avgs.Size(); i++) 00763 avgs(i) /= int_psi(i); 00764 } 00765 00766 void GridFunction::GetNodalValues(Vector &nval, int vdim) const 00767 { 00768 int i, j; 00769 Array<int> vertices; 00770 Array<double> values; 00771 Array<int> overlap(fes->GetNV()); 00772 nval.SetSize(fes->GetNV()); 00773 00774 for (i = 0; i < overlap.Size(); i++) 00775 { 00776 nval(i) = 0.0; 00777 overlap[i] = 0; 00778 } 00779 for (i = 0; i < fes->GetNE(); i++) 00780 { 00781 fes->GetElementVertices(i, vertices); 00782 GetNodalValues(i, values, vdim); 00783 for (j = 0; j < vertices.Size(); j++) 00784 { 00785 nval(vertices[j]) += values[j]; 00786 overlap[vertices[j]]++; 00787 } 00788 } 00789 for (i = 0; i < overlap.Size(); i++) 00790 nval(i) /= overlap[i]; 00791 } 00792 00793 void GridFunction::ProjectCoefficient(Coefficient &coeff) 00794 { 00795 int i; 00796 Array<int> vdofs; 00797 Vector vals; 00798 00799 DeltaCoefficient *delta_c = dynamic_cast<DeltaCoefficient *>(&coeff); 00800 00801 if (delta_c == NULL) 00802 { 00803 for (i = 0; i < fes->GetNE(); i++) 00804 { 00805 fes->GetElementVDofs(i, vdofs); 00806 vals.SetSize(vdofs.Size()); 00807 fes->GetFE(i)->Project(coeff, *fes->GetElementTransformation(i), vals); 00808 SetSubVector(vdofs, vals); 00809 } 00810 } 00811 else 00812 { 00813 Mesh *mesh = fes->GetMesh(); 00814 const int dim = mesh->Dimension(); 00815 const double *center = delta_c->Center(); 00816 const double *vert = mesh->GetVertex(0); 00817 double min_dist, dist; 00818 int v_idx = 0; 00819 00820 // find the vertex closest to the center of the delta function 00821 min_dist = Distance(center, vert, dim); 00822 for (int i = 0; i < mesh->GetNV(); i++) 00823 { 00824 vert = mesh->GetVertex(i); 00825 dist = Distance(center, vert, dim); 00826 if (dist < min_dist) 00827 { 00828 min_dist = dist; 00829 v_idx = i; 00830 } 00831 } 00832 00833 (*this) = 0.0; 00834 00835 if (min_dist >= delta_c->Tol()) 00836 return; 00837 00838 // find the elements that have 'v_idx' as a vertex 00839 MassIntegrator Mi(*delta_c->Weight()); 00840 DenseMatrix loc_mass; 00841 Array<int> vertices; 00842 Vector loc_mass_vals; 00843 double integral = 0.0; 00844 for (int i = 0; i < mesh->GetNE(); i++) 00845 { 00846 mesh->GetElementVertices(i, vertices); 00847 for (int j = 0; j < vertices.Size(); j++) 00848 if (vertices[j] == v_idx) 00849 { 00850 const FiniteElement *fe = fes->GetFE(i); 00851 Mi.AssembleElementMatrix(*fe, *fes->GetElementTransformation(i), 00852 loc_mass); 00853 vals.SetSize(fe->GetDof()); 00854 fe->ProjectDelta(j, vals); 00855 fes->GetElementVDofs(i, vdofs); 00856 SetSubVector(vdofs, vals); 00857 loc_mass_vals.SetSize(vals.Size()); 00858 loc_mass.Mult(vals, loc_mass_vals); 00859 for (int k = 0; k < loc_mass_vals.Size(); k++) 00860 integral += loc_mass_vals(k); 00861 break; 00862 } 00863 } 00864 00865 (*this) *= (delta_c->Scale() / integral); 00866 } 00867 } 00868 00869 void GridFunction::ProjectCoefficient( 00870 Coefficient &coeff, Array<int> &dofs, int vd) 00871 { 00872 int el = -1; 00873 ElementTransformation *T = NULL; 00874 const FiniteElement *fe = NULL; 00875 00876 for (int i = 0; i < dofs.Size(); i++) 00877 { 00878 int dof = dofs[i], j = fes->GetElementForDof(dof); 00879 if (el != j) 00880 { 00881 el = j; 00882 T = fes->GetElementTransformation(el); 00883 fe = fes->GetFE(el); 00884 } 00885 int vdof = fes->DofToVDof(dof, vd); 00886 int ld = fes->GetLocalDofForDof(dof); 00887 const IntegrationPoint &ip = fe->GetNodes().IntPoint(ld); 00888 T->SetIntPoint(&ip); 00889 (*this)(vdof) = coeff.Eval(*T, ip); 00890 } 00891 } 00892 00893 void GridFunction::ProjectCoefficient(VectorCoefficient &vcoeff) 00894 { 00895 int i; 00896 Array<int> vdofs; 00897 Vector vals; 00898 00899 for (i = 0; i < fes->GetNE(); i++) 00900 { 00901 fes->GetElementVDofs(i, vdofs); 00902 vals.SetSize(vdofs.Size()); 00903 fes->GetFE(i)->Project(vcoeff, *fes->GetElementTransformation(i), vals); 00904 SetSubVector(vdofs, vals); 00905 } 00906 } 00907 00908 void GridFunction::ProjectCoefficient(Coefficient *coeff[]) 00909 { 00910 int i, j, fdof, d, ind; 00911 double val; 00912 const FiniteElement *fe; 00913 ElementTransformation *transf; 00914 Array<int> vdofs; 00915 00916 for (i = 0; i < fes->GetNE(); i++) 00917 { 00918 fe = fes->GetFE(i); 00919 fdof = fe->GetDof(); 00920 transf = fes->GetElementTransformation(i); 00921 const IntegrationRule &ir = fe->GetNodes(); 00922 fes->GetElementVDofs(i, vdofs); 00923 for (j = 0; j < fdof; j++) 00924 { 00925 const IntegrationPoint &ip = ir.IntPoint(j); 00926 transf->SetIntPoint(&ip); 00927 for (d = 0; d < fes->GetVDim(); d++) 00928 { 00929 val = coeff[d]->Eval(*transf, ip); 00930 if ( (ind = vdofs[fdof*d+j]) < 0 ) 00931 val = -val, ind = -1-ind; 00932 (*this)(ind) = val; 00933 } 00934 } 00935 } 00936 } 00937 00938 void GridFunction::ProjectBdrCoefficient( 00939 Coefficient *coeff[], Array<int> &attr) 00940 { 00941 int i, j, fdof, d, ind; 00942 double val; 00943 const FiniteElement *fe; 00944 ElementTransformation *transf; 00945 Array<int> vdofs; 00946 00947 for (i = 0; i < fes->GetNBE(); i++) 00948 { 00949 if ( attr[fes->GetBdrAttribute(i)-1] ) 00950 { 00951 fe = fes->GetBE(i); 00952 fdof = fe->GetDof(); 00953 transf = fes->GetBdrElementTransformation(i); 00954 const IntegrationRule &ir = fe->GetNodes(); 00955 fes->GetBdrElementVDofs(i, vdofs); 00956 for (j = 0; j < fdof; j++) 00957 { 00958 const IntegrationPoint &ip = ir.IntPoint(j); 00959 transf->SetIntPoint(&ip); 00960 for (d = 0; d < fes->GetVDim(); d++) 00961 { 00962 val = coeff[d]->Eval(*transf, ip); 00963 if ( (ind = vdofs[fdof*d+j]) < 0 ) 00964 val = -val, ind = -1-ind; 00965 (*this)(ind) = val; 00966 } 00967 } 00968 } 00969 } 00970 } 00971 00972 void GridFunction::ProjectBdrCoefficientNormal( 00973 VectorCoefficient &vcoeff, Array<int> &bdr_attr) 00974 { 00975 #if 0 00976 // implementation for the case when the face dofs are integrals of the 00977 // normal component. 00978 const FiniteElement *fe; 00979 ElementTransformation *T; 00980 Array<int> dofs; 00981 int dim = vcoeff.GetVDim(); 00982 Vector vc(dim), nor(dim), lvec, shape; 00983 00984 for (int i = 0; i < fes->GetNBE(); i++) 00985 { 00986 if (bdr_attr[fes->GetBdrAttribute(i)-1] == 0) 00987 continue; 00988 fe = fes->GetBE(i); 00989 T = fes->GetBdrElementTransformation(i); 00990 int intorder = 2*fe->GetOrder(); // !!! 00991 const IntegrationRule &ir = IntRules.Get(fe->GetGeomType(), intorder); 00992 int nd = fe->GetDof(); 00993 lvec.SetSize(nd); 00994 shape.SetSize(nd); 00995 lvec = 0.0; 00996 for (int j = 0; j < ir.GetNPoints(); j++) 00997 { 00998 const IntegrationPoint &ip = ir.IntPoint(j); 00999 T->SetIntPoint(&ip); 01000 vcoeff.Eval(vc, *T, ip); 01001 const DenseMatrix &J = T->Jacobian(); 01002 if (dim == 2) 01003 { 01004 nor(0) = J(1,0); 01005 nor(1) = -J(0,0); 01006 } 01007 else if (dim == 3) 01008 { 01009 nor(0) = J(1,0)*J(2,1) - J(2,0)*J(1,1); 01010 nor(1) = J(2,0)*J(0,1) - J(0,0)*J(2,1); 01011 nor(2) = J(0,0)*J(1,1) - J(1,0)*J(0,1); 01012 } 01013 fe->CalcShape(ip, shape); 01014 lvec.Add(ip.weight * (vc * nor), shape); 01015 } 01016 fes->GetBdrElementDofs(i, dofs); 01017 SetSubVector(dofs, lvec); 01018 } 01019 #else 01020 // implementation for the case when the face dofs are scaled point 01021 // values of the normal component. 01022 const FiniteElement *fe; 01023 ElementTransformation *T; 01024 Array<int> dofs; 01025 int dim = vcoeff.GetVDim(); 01026 Vector vc(dim), nor(dim), lvec; 01027 01028 for (int i = 0; i < fes->GetNBE(); i++) 01029 { 01030 if (bdr_attr[fes->GetBdrAttribute(i)-1] == 0) 01031 continue; 01032 fe = fes->GetBE(i); 01033 T = fes->GetBdrElementTransformation(i); 01034 const IntegrationRule &ir = fe->GetNodes(); 01035 lvec.SetSize(fe->GetDof()); 01036 for (int j = 0; j < ir.GetNPoints(); j++) 01037 { 01038 const IntegrationPoint &ip = ir.IntPoint(j); 01039 T->SetIntPoint(&ip); 01040 vcoeff.Eval(vc, *T, ip); 01041 const DenseMatrix &J = T->Jacobian(); 01042 if (dim == 2) 01043 { 01044 nor(0) = J(1,0); 01045 nor(1) = -J(0,0); 01046 } 01047 else if (dim == 3) 01048 { 01049 nor(0) = J(1,0)*J(2,1) - J(2,0)*J(1,1); 01050 nor(1) = J(2,0)*J(0,1) - J(0,0)*J(2,1); 01051 nor(2) = J(0,0)*J(1,1) - J(1,0)*J(0,1); 01052 } 01053 lvec(j) = (vc * nor); 01054 } 01055 fes->GetBdrElementDofs(i, dofs); 01056 SetSubVector(dofs, lvec); 01057 } 01058 #endif 01059 } 01060 01061 void GridFunction::ProjectBdrCoefficientTangent( 01062 VectorCoefficient &vcoeff, Array<int> &bdr_attr) 01063 { 01064 const FiniteElement *fe; 01065 ElementTransformation *T; 01066 Array<int> dofs; 01067 Vector lvec; 01068 01069 for (int i = 0; i < fes->GetNBE(); i++) 01070 { 01071 if (bdr_attr[fes->GetBdrAttribute(i)-1] == 0) 01072 continue; 01073 fe = fes->GetBE(i); 01074 T = fes->GetBdrElementTransformation(i); 01075 fes->GetBdrElementDofs(i, dofs); 01076 lvec.SetSize(fe->GetDof()); 01077 fe->Project(vcoeff, *T, lvec); 01078 SetSubVector(dofs, lvec); 01079 } 01080 } 01081 01082 double GridFunction::ComputeL2Error( 01083 Coefficient *exsol[], const IntegrationRule *irs[]) const 01084 { 01085 double error = 0.0, a; 01086 const FiniteElement *fe; 01087 ElementTransformation *transf; 01088 Vector shape; 01089 Array<int> vdofs; 01090 int fdof, d, i, intorder, j, k; 01091 01092 for (i = 0; i < fes->GetNE(); i++) 01093 { 01094 fe = fes->GetFE(i); 01095 fdof = fe->GetDof(); 01096 transf = fes->GetElementTransformation(i); 01097 shape.SetSize(fdof); 01098 intorder = 2*fe->GetOrder() + 1; // <---------- 01099 const IntegrationRule *ir; 01100 if (irs) 01101 ir = irs[fe->GetGeomType()]; 01102 else 01103 ir = &(IntRules.Get(fe->GetGeomType(), intorder)); 01104 fes->GetElementVDofs(i, vdofs); 01105 for (j = 0; j < ir->GetNPoints(); j++) 01106 { 01107 const IntegrationPoint &ip = ir->IntPoint(j); 01108 fe->CalcShape(ip, shape); 01109 for (d = 0; d < fes->GetVDim(); d++) 01110 { 01111 a = 0; 01112 for (k = 0; k < fdof; k++) 01113 if (vdofs[fdof*d+k] >= 0) 01114 a += (*this)(vdofs[fdof*d+k]) * shape(k); 01115 else 01116 a -= (*this)(-1-vdofs[fdof*d+k]) * shape(k); 01117 transf->SetIntPoint(&ip); 01118 a -= exsol[d]->Eval(*transf, ip); 01119 error += ip.weight * transf->Weight() * a * a; 01120 } 01121 } 01122 } 01123 01124 if (error < 0.0) 01125 return -sqrt(-error); 01126 return sqrt(error); 01127 } 01128 01129 double GridFunction::ComputeL2Error( 01130 VectorCoefficient &exsol, const IntegrationRule *irs[], 01131 Array<int> *elems) const 01132 { 01133 double error = 0.0; 01134 const FiniteElement *fe; 01135 ElementTransformation *T; 01136 DenseMatrix vals, exact_vals, tr; 01137 Vector loc_errs; 01138 01139 for (int i = 0; i < fes->GetNE(); i++) 01140 { 01141 if (elems != NULL && (*elems)[i] == 0) continue; 01142 fe = fes->GetFE(i); 01143 int intorder = 2*fe->GetOrder() + 1; // <---------- 01144 const IntegrationRule *ir; 01145 if (irs) 01146 ir = irs[fe->GetGeomType()]; 01147 else 01148 ir = &(IntRules.Get(fe->GetGeomType(), intorder)); 01149 GetVectorValues(i, *ir, vals, tr); 01150 T = fes->GetElementTransformation(i); 01151 exsol.Eval(exact_vals, *T, *ir); 01152 vals -= exact_vals; 01153 loc_errs.SetSize(vals.Width()); 01154 vals.Norm2(loc_errs); 01155 for (int j = 0; j < ir->GetNPoints(); j++) 01156 { 01157 const IntegrationPoint &ip = ir->IntPoint(j); 01158 T->SetIntPoint(&ip); 01159 error += ip.weight * T->Weight() * (loc_errs(j) * loc_errs(j)); 01160 } 01161 } 01162 01163 if (error < 0.0) 01164 return -sqrt(-error); 01165 return sqrt(error); 01166 } 01167 01168 double GridFunction::ComputeH1Error( 01169 Coefficient *exsol, VectorCoefficient *exgrad, 01170 Coefficient *ell_coeff, double Nu, int norm_type) const 01171 { 01172 // assuming vdim is 1 01173 int i, fdof, dim, intorder, j, k; 01174 Mesh *mesh; 01175 const FiniteElement *fe; 01176 ElementTransformation *transf; 01177 FaceElementTransformations *face_elem_transf; 01178 Vector e_grad, a_grad, shape, el_dofs, err_val, ell_coeff_val; 01179 DenseMatrix dshape, dshapet, Jinv; 01180 Array<int> vdofs; 01181 IntegrationPoint eip; 01182 double error = 0.0; 01183 01184 mesh = fes->GetMesh(); 01185 dim = mesh->Dimension(); 01186 e_grad.SetSize(dim); 01187 a_grad.SetSize(dim); 01188 Jinv.SetSize(dim); 01189 01190 if (norm_type & 1) 01191 for (i = 0; i < mesh->GetNE(); i++) 01192 { 01193 fe = fes->GetFE(i); 01194 fdof = fe->GetDof(); 01195 transf = mesh->GetElementTransformation(i); 01196 el_dofs.SetSize(fdof); 01197 dshape.SetSize(fdof, dim); 01198 dshapet.SetSize(fdof, dim); 01199 intorder = 2 * fe->GetOrder(); // <---------- 01200 const IntegrationRule &ir = IntRules.Get(fe->GetGeomType(), intorder); 01201 fes->GetElementVDofs(i, vdofs); 01202 for (k = 0; k < fdof; k++) 01203 if (vdofs[k] >= 0) 01204 el_dofs(k) = (*this)(vdofs[k]); 01205 else 01206 el_dofs(k) = - (*this)(-1-vdofs[k]); 01207 for (j = 0; j < ir.GetNPoints(); j++) 01208 { 01209 const IntegrationPoint &ip = ir.IntPoint(j); 01210 fe->CalcDShape(ip, dshape); 01211 transf->SetIntPoint(&ip); 01212 exgrad->Eval(e_grad, *transf, ip); 01213 CalcInverse(transf->Jacobian(), Jinv); 01214 Mult(dshape, Jinv, dshapet); 01215 dshapet.MultTranspose(el_dofs, a_grad); 01216 e_grad -= a_grad; 01217 error += (ip.weight * transf->Weight() * 01218 ell_coeff->Eval(*transf, ip) * 01219 (e_grad * e_grad)); 01220 } 01221 } 01222 01223 if (norm_type & 2) 01224 for (i = 0; i < mesh->GetNFaces(); i++) 01225 { 01226 face_elem_transf = mesh->GetFaceElementTransformations(i, 5); 01227 int i1 = face_elem_transf->Elem1No; 01228 int i2 = face_elem_transf->Elem2No; 01229 intorder = fes->GetFE(i1)->GetOrder(); 01230 if (i2 >= 0) 01231 if ( (k = fes->GetFE(i2)->GetOrder()) > intorder ) 01232 intorder = k; 01233 intorder = 2 * intorder; // <------------- 01234 const IntegrationRule &ir = 01235 IntRules.Get(face_elem_transf->FaceGeom, intorder); 01236 err_val.SetSize(ir.GetNPoints()); 01237 ell_coeff_val.SetSize(ir.GetNPoints()); 01238 // side 1 01239 transf = face_elem_transf->Elem1; 01240 fe = fes->GetFE(i1); 01241 fdof = fe->GetDof(); 01242 fes->GetElementVDofs(i1, vdofs); 01243 shape.SetSize(fdof); 01244 el_dofs.SetSize(fdof); 01245 for (k = 0; k < fdof; k++) 01246 if (vdofs[k] >= 0) 01247 el_dofs(k) = (*this)(vdofs[k]); 01248 else 01249 el_dofs(k) = - (*this)(-1-vdofs[k]); 01250 for (j = 0; j < ir.GetNPoints(); j++) 01251 { 01252 face_elem_transf->Loc1.Transform(ir.IntPoint(j), eip); 01253 fe->CalcShape(eip, shape); 01254 transf->SetIntPoint(&eip); 01255 ell_coeff_val(j) = ell_coeff->Eval(*transf, eip); 01256 err_val(j) = exsol->Eval(*transf, eip) - (shape * el_dofs); 01257 } 01258 if (i2 >= 0) 01259 { 01260 // side 2 01261 face_elem_transf = mesh->GetFaceElementTransformations(i, 10); 01262 transf = face_elem_transf->Elem2; 01263 fe = fes->GetFE(i2); 01264 fdof = fe->GetDof(); 01265 fes->GetElementVDofs(i2, vdofs); 01266 shape.SetSize(fdof); 01267 el_dofs.SetSize(fdof); 01268 for (k = 0; k < fdof; k++) 01269 if (vdofs[k] >= 0) 01270 el_dofs(k) = (*this)(vdofs[k]); 01271 else 01272 el_dofs(k) = - (*this)(-1-vdofs[k]); 01273 for (j = 0; j < ir.GetNPoints(); j++) 01274 { 01275 face_elem_transf->Loc2.Transform(ir.IntPoint(j), eip); 01276 fe->CalcShape(eip, shape); 01277 transf->SetIntPoint(&eip); 01278 ell_coeff_val(j) += ell_coeff->Eval(*transf, eip); 01279 ell_coeff_val(j) *= 0.5; 01280 err_val(j) -= (exsol->Eval(*transf, eip) - (shape * el_dofs)); 01281 } 01282 } 01283 face_elem_transf = mesh->GetFaceElementTransformations(i, 16); 01284 transf = face_elem_transf->Face; 01285 for (j = 0; j < ir.GetNPoints(); j++) 01286 { 01287 const IntegrationPoint &ip = ir.IntPoint(j); 01288 transf->SetIntPoint(&ip); 01289 error += (ip.weight * Nu * ell_coeff_val(j) * 01290 pow(transf->Weight(), 1.0-1.0/(dim-1)) * 01291 err_val(j) * err_val(j)); 01292 } 01293 } 01294 01295 if (error < 0.0) 01296 return -sqrt(-error); 01297 return sqrt(error); 01298 } 01299 01300 double GridFunction::ComputeMaxError( 01301 Coefficient *exsol[], const IntegrationRule *irs[]) const 01302 { 01303 double error = 0.0, a; 01304 const FiniteElement *fe; 01305 ElementTransformation *transf; 01306 Vector shape; 01307 Array<int> vdofs; 01308 int fdof, d, i, intorder, j, k; 01309 01310 for (i = 0; i < fes->GetNE(); i++) 01311 { 01312 fe = fes->GetFE(i); 01313 fdof = fe->GetDof(); 01314 transf = fes->GetElementTransformation(i); 01315 shape.SetSize(fdof); 01316 intorder = 2*fe->GetOrder() + 1; // <---------- 01317 const IntegrationRule *ir; 01318 if (irs) 01319 ir = irs[fe->GetGeomType()]; 01320 else 01321 ir = &(IntRules.Get(fe->GetGeomType(), intorder)); 01322 fes->GetElementVDofs(i, vdofs); 01323 for (j = 0; j < ir->GetNPoints(); j++) 01324 { 01325 const IntegrationPoint &ip = ir->IntPoint(j); 01326 fe->CalcShape(ip, shape); 01327 transf->SetIntPoint(&ip); 01328 for (d = 0; d < fes->GetVDim(); d++) 01329 { 01330 a = 0; 01331 for (k = 0; k < fdof; k++) 01332 if (vdofs[fdof*d+k] >= 0) 01333 a += (*this)(vdofs[fdof*d+k]) * shape(k); 01334 else 01335 a -= (*this)(-1-vdofs[fdof*d+k]) * shape(k); 01336 a -= exsol[d]->Eval(*transf, ip); 01337 a = fabs(a); 01338 if (error < a) 01339 error = a; 01340 } 01341 } 01342 } 01343 01344 return error; 01345 } 01346 01347 double GridFunction::ComputeMaxError( 01348 VectorCoefficient &exsol, const IntegrationRule *irs[]) const 01349 { 01350 double error = 0.0; 01351 const FiniteElement *fe; 01352 ElementTransformation *T; 01353 DenseMatrix vals, exact_vals, tr; 01354 Vector loc_errs; 01355 01356 for (int i = 0; i < fes->GetNE(); i++) 01357 { 01358 fe = fes->GetFE(i); 01359 int intorder = 2*fe->GetOrder() + 1; // <---------- 01360 const IntegrationRule *ir; 01361 if (irs) 01362 ir = irs[fe->GetGeomType()]; 01363 else 01364 ir = &(IntRules.Get(fe->GetGeomType(), intorder)); 01365 GetVectorValues(i, *ir, vals, tr); 01366 T = fes->GetElementTransformation(i); 01367 exsol.Eval(exact_vals, *T, *ir); 01368 vals -= exact_vals; 01369 loc_errs.SetSize(vals.Width()); 01370 // compute the lengths of the errors at the integration points 01371 // thus the vector max. norm is rotationally invariant 01372 vals.Norm2(loc_errs); 01373 double loc_error = loc_errs.Normlinf(); 01374 if (error < loc_error) 01375 error = loc_error; 01376 } 01377 01378 return error; 01379 } 01380 01381 double GridFunction::ComputeW11Error( 01382 Coefficient *exsol, VectorCoefficient *exgrad, int norm_type, 01383 Array<int> *elems, const IntegrationRule *irs[]) const 01384 { 01385 // assuming vdim is 1 01386 int i, fdof, dim, intorder, j, k; 01387 Mesh *mesh; 01388 const FiniteElement *fe; 01389 ElementTransformation *transf; 01390 Vector e_grad, a_grad, shape, el_dofs, err_val, ell_coeff_val; 01391 DenseMatrix dshape, dshapet, Jinv; 01392 Array<int> vdofs; 01393 double a, error = 0.0; 01394 01395 mesh = fes->GetMesh(); 01396 dim = mesh->Dimension(); 01397 e_grad.SetSize(dim); 01398 a_grad.SetSize(dim); 01399 Jinv.SetSize(dim); 01400 01401 if (norm_type & 1) // L_1 norm 01402 for (i = 0; i < mesh->GetNE(); i++) 01403 { 01404 if (elems != NULL && (*elems)[i] == 0) continue; 01405 fe = fes->GetFE(i); 01406 fdof = fe->GetDof(); 01407 transf = fes->GetElementTransformation(i); 01408 el_dofs.SetSize(fdof); 01409 shape.SetSize(fdof); 01410 intorder = 2*fe->GetOrder() + 1; // <---------- 01411 const IntegrationRule *ir; 01412 if (irs) 01413 ir = irs[fe->GetGeomType()]; 01414 else 01415 ir = &(IntRules.Get(fe->GetGeomType(), intorder)); 01416 fes->GetElementVDofs(i, vdofs); 01417 for (k = 0; k < fdof; k++) 01418 if (vdofs[k] >= 0) 01419 el_dofs(k) = (*this)(vdofs[k]); 01420 else 01421 el_dofs(k) = -(*this)(-1-vdofs[k]); 01422 for (j = 0; j < ir->GetNPoints(); j++) 01423 { 01424 const IntegrationPoint &ip = ir->IntPoint(j); 01425 fe->CalcShape(ip, shape); 01426 transf->SetIntPoint(&ip); 01427 a = (el_dofs * shape) - (exsol->Eval(*transf, ip)); 01428 error += ip.weight * transf->Weight() * fabs(a); 01429 } 01430 } 01431 01432 if (norm_type & 2) // W^1_1 seminorm 01433 for (i = 0; i < mesh->GetNE(); i++) 01434 { 01435 if (elems != NULL && (*elems)[i] == 0) continue; 01436 fe = fes->GetFE(i); 01437 fdof = fe->GetDof(); 01438 transf = mesh->GetElementTransformation(i); 01439 el_dofs.SetSize(fdof); 01440 dshape.SetSize(fdof, dim); 01441 dshapet.SetSize(fdof, dim); 01442 intorder = 2*fe->GetOrder() + 1; // <---------- 01443 const IntegrationRule *ir; 01444 if (irs) 01445 ir = irs[fe->GetGeomType()]; 01446 else 01447 ir = &(IntRules.Get(fe->GetGeomType(), intorder)); 01448 fes->GetElementVDofs(i, vdofs); 01449 for (k = 0; k < fdof; k++) 01450 if (vdofs[k] >= 0) 01451 el_dofs(k) = (*this)(vdofs[k]); 01452 else 01453 el_dofs(k) = -(*this)(-1-vdofs[k]); 01454 for (j = 0; j < ir->GetNPoints(); j++) 01455 { 01456 const IntegrationPoint &ip = ir->IntPoint(j); 01457 fe->CalcDShape(ip, dshape); 01458 transf->SetIntPoint(&ip); 01459 exgrad->Eval(e_grad, *transf, ip); 01460 CalcInverse(transf->Jacobian(), Jinv); 01461 Mult(dshape, Jinv, dshapet); 01462 dshapet.MultTranspose(el_dofs, a_grad); 01463 e_grad -= a_grad; 01464 error += ip.weight * transf->Weight() * e_grad.Norml1(); 01465 } 01466 } 01467 01468 return error; 01469 } 01470 01471 double GridFunction::ComputeL1Error( 01472 VectorCoefficient &exsol, const IntegrationRule *irs[]) const 01473 { 01474 double error = 0.0; 01475 const FiniteElement *fe; 01476 ElementTransformation *T; 01477 DenseMatrix vals, exact_vals, tr; 01478 Vector loc_errs; 01479 01480 for (int i = 0; i < fes->GetNE(); i++) 01481 { 01482 fe = fes->GetFE(i); 01483 int intorder = 2*fe->GetOrder() + 1; // <---------- 01484 const IntegrationRule *ir; 01485 if (irs) 01486 ir = irs[fe->GetGeomType()]; 01487 else 01488 ir = &(IntRules.Get(fe->GetGeomType(), intorder)); 01489 GetVectorValues(i, *ir, vals, tr); 01490 T = fes->GetElementTransformation(i); 01491 exsol.Eval(exact_vals, *T, *ir); 01492 vals -= exact_vals; 01493 loc_errs.SetSize(vals.Width()); 01494 // compute the lengths of the errors at the integration points 01495 // thus the vector L_1 norm is rotationally invariant 01496 vals.Norm2(loc_errs); 01497 for (int j = 0; j < ir->GetNPoints(); j++) 01498 { 01499 const IntegrationPoint &ip = ir->IntPoint(j); 01500 T->SetIntPoint(&ip); 01501 error += ip.weight * T->Weight() * loc_errs(j); 01502 } 01503 } 01504 01505 return error; 01506 } 01507 01508 GridFunction & GridFunction::operator=(double value) 01509 { 01510 for (int i = 0; i < size; i++) 01511 data[i] = value; 01512 return *this; 01513 } 01514 01515 GridFunction & GridFunction::operator=(const Vector &v) 01516 { 01517 for (int i = 0; i < size; i++) 01518 data[i] = v(i); 01519 return *this; 01520 } 01521 01522 GridFunction & GridFunction::operator=(const GridFunction &v) 01523 { 01524 return this->operator=((const Vector &)v); 01525 } 01526 01527 void GridFunction::Save(ostream &out) 01528 { 01529 fes->Save(out); 01530 out << '\n'; 01531 if (fes->GetOrdering() == Ordering::byNODES) 01532 Vector::Print(out, 1); 01533 else 01534 Vector::Print(out, fes->GetVDim()); 01535 } 01536 01537 void GridFunction::SaveVTK(ostream &out, const string &field_name, int ref) 01538 { 01539 Mesh *mesh = fes->GetMesh(); 01540 RefinedGeometry *RefG; 01541 Vector val; 01542 DenseMatrix vval, pmat; 01543 01544 if (VectorDim() == 1) 01545 { 01546 // scalar data 01547 out << "SCALARS " << field_name << " double 1\n" 01548 << "LOOKUP_TABLE default\n"; 01549 for (int i = 0; i < mesh->GetNE(); i++) 01550 { 01551 RefG = GlobGeometryRefiner.Refine( 01552 mesh->GetElementBaseGeometry(i), ref, 1); 01553 01554 GetValues(i, RefG->RefPts, val, pmat); 01555 01556 for (int j = 0; j < val.Size(); j++) 01557 { 01558 out << val(j) << '\n'; 01559 } 01560 } 01561 } 01562 else 01563 { 01564 // vector data 01565 out << "VECTORS " << field_name << " double\n"; 01566 for (int i = 0; i < mesh->GetNE(); i++) 01567 { 01568 RefG = GlobGeometryRefiner.Refine( 01569 mesh->GetElementBaseGeometry(i), ref, 1); 01570 01571 GetVectorValues(i, RefG->RefPts, vval, pmat); 01572 01573 for (int j = 0; j < vval.Width(); j++) 01574 { 01575 out << vval(0, j) << ' ' << vval(1, j) << ' '; 01576 if (vval.Height() == 2) 01577 out << 0.0; 01578 else 01579 out << vval(2, j); 01580 out << '\n'; 01581 } 01582 } 01583 } 01584 } 01585 01586 void GridFunction::SaveSTLTri(ostream &out, double p1[], double p2[], 01587 double p3[]) 01588 { 01589 double v1[3] = { p2[0] - p1[0], p2[1] - p1[1], p2[2] - p1[2] }; 01590 double v2[3] = { p3[0] - p1[0], p3[1] - p1[1], p3[2] - p1[2] }; 01591 double n[] = { v1[1] * v2[2] - v1[2] * v2[1], 01592 v1[2] * v2[0] - v1[0] * v2[2], 01593 v1[0] * v2[1] - v1[1] * v2[0] }; 01594 double rl = 1.0 / sqrt(n[0] * n[0] + n[1] * n[1] + n[2] * n[2]); 01595 n[0] *= rl; n[1] *= rl; n[2] *= rl; 01596 01597 out << " facet normal " << n[0] << ' ' << n[1] << ' ' << n[2] 01598 << "\n outer loop" 01599 << "\n vertex " << p1[0] << ' ' << p1[1] << ' ' << p1[2] 01600 << "\n vertex " << p2[0] << ' ' << p2[1] << ' ' << p2[2] 01601 << "\n vertex " << p3[0] << ' ' << p3[1] << ' ' << p3[2] 01602 << "\n endloop\n endfacet\n"; 01603 } 01604 01605 void GridFunction::SaveSTL(ostream &out, int TimesToRefine) 01606 { 01607 Mesh *mesh = fes->GetMesh(); 01608 01609 if (mesh->Dimension() != 2) 01610 return; 01611 01612 int i, j, k, l, n; 01613 DenseMatrix pointmat; 01614 Vector values; 01615 RefinedGeometry * RefG; 01616 double pts[4][3], bbox[3][2]; 01617 01618 out << "solid GridFunction\n"; 01619 01620 bbox[0][0] = bbox[0][1] = bbox[1][0] = bbox[1][1] = 01621 bbox[2][0] = bbox[2][1] = 0.0; 01622 for (i = 0; i < mesh->GetNE(); i++) 01623 { 01624 n = fes->GetFE(i)->GetGeomType(); 01625 RefG = GlobGeometryRefiner.Refine(n, TimesToRefine); 01626 GetValues(i, RefG->RefPts, values, pointmat); 01627 Array<int> &RG = RefG->RefGeoms; 01628 n = Geometries.NumBdr(n); 01629 for (k = 0; k < RG.Size()/n; k++) 01630 { 01631 for (j = 0; j < n; j++) 01632 { 01633 l = RG[n*k+j]; 01634 pts[j][0] = pointmat(0,l); 01635 pts[j][1] = pointmat(1,l); 01636 pts[j][2] = values(l); 01637 } 01638 01639 if (n == 3) 01640 { 01641 SaveSTLTri(out, pts[0], pts[1], pts[2]); 01642 } 01643 else 01644 { 01645 SaveSTLTri(out, pts[0], pts[1], pts[2]); 01646 SaveSTLTri(out, pts[0], pts[2], pts[3]); 01647 } 01648 } 01649 01650 if (i == 0) 01651 { 01652 bbox[0][0] = pointmat(0,0); 01653 bbox[0][1] = pointmat(0,0); 01654 bbox[1][0] = pointmat(1,0); 01655 bbox[1][1] = pointmat(1,0); 01656 bbox[2][0] = values(0); 01657 bbox[2][1] = values(0); 01658 } 01659 01660 for (j = 0; j < values.Size(); j++) 01661 { 01662 if (bbox[0][0] > pointmat(0,j)) 01663 bbox[0][0] = pointmat(0,j); 01664 if (bbox[0][1] < pointmat(0,j)) 01665 bbox[0][1] = pointmat(0,j); 01666 if (bbox[1][0] > pointmat(1,j)) 01667 bbox[1][0] = pointmat(1,j); 01668 if (bbox[1][1] < pointmat(1,j)) 01669 bbox[1][1] = pointmat(1,j); 01670 if (bbox[2][0] > values(j)) 01671 bbox[2][0] = values(j); 01672 if (bbox[2][1] < values(j)) 01673 bbox[2][1] = values(j); 01674 } 01675 } 01676 01677 cout << "[xmin,xmax] = [" << bbox[0][0] << ',' << bbox[0][1] << "]\n" 01678 << "[ymin,ymax] = [" << bbox[1][0] << ',' << bbox[1][1] << "]\n" 01679 << "[zmin,zmax] = [" << bbox[2][0] << ',' << bbox[2][1] << ']' 01680 << endl; 01681 01682 out << "endsolid GridFunction" << endl; 01683 } 01684 01685 01686 void ComputeFlux(BilinearFormIntegrator &blfi, 01687 GridFunction &u, 01688 GridFunction &flux, int wcoef, int sd) 01689 { 01690 int i, j, nfe; 01691 FiniteElementSpace *ufes, *ffes; 01692 ElementTransformation *Transf; 01693 01694 ufes = u.FESpace(); 01695 ffes = flux.FESpace(); 01696 nfe = ufes->GetNE(); 01697 Array<int> udofs; 01698 Array<int> fdofs; 01699 Array<int> overlap(flux.Size()); 01700 Vector ul, fl; 01701 01702 flux = 0.0; 01703 01704 for (i = 0; i < overlap.Size(); i++) 01705 overlap[i] = 0; 01706 01707 for (i = 0; i < nfe; i++) 01708 if (sd < 0 || ufes->GetAttribute(i) == sd) 01709 { 01710 ufes->GetElementVDofs(i, udofs); 01711 ffes->GetElementVDofs(i, fdofs); 01712 01713 ul.SetSize(udofs.Size()); 01714 for (j = 0; j < ul.Size(); j++) 01715 ul(j) = u(udofs[j]); 01716 01717 Transf = ufes->GetElementTransformation(i); 01718 blfi.ComputeElementFlux(*ufes->GetFE(i), *Transf, ul, 01719 *ffes->GetFE(i), fl, wcoef); 01720 01721 flux.AddElementVector(fdofs, fl); 01722 01723 for (j = 0; j < fdofs.Size(); j++) 01724 overlap[fdofs[j]]++; 01725 } 01726 01727 for (i = 0; i < overlap.Size(); i++) 01728 if (overlap[i] != 0) 01729 flux(i) /= overlap[i]; 01730 } 01731 01732 void ZZErrorEstimator(BilinearFormIntegrator &blfi, 01733 GridFunction &u, 01734 GridFunction &flux, Vector &ErrorEstimates, 01735 int wsd) 01736 { 01737 int i, j, s, nfe, nsd; 01738 FiniteElementSpace *ufes, *ffes; 01739 ElementTransformation *Transf; 01740 01741 ufes = u.FESpace(); 01742 ffes = flux.FESpace(); 01743 nfe = ufes->GetNE(); 01744 Array<int> udofs; 01745 Array<int> fdofs; 01746 Vector ul, fl, fla; 01747 01748 ErrorEstimates.SetSize(nfe); 01749 01750 nsd = 1; 01751 if (wsd) 01752 for (i = 0; i < nfe; i++) 01753 if ( (j=ufes->GetAttribute(i)) > nsd) 01754 nsd = j; 01755 01756 for (s = 1; s <= nsd; s++) 01757 { 01758 if (wsd) 01759 ComputeFlux(blfi, u, flux, 0, s); 01760 else 01761 ComputeFlux(blfi, u, flux, 0); 01762 01763 for (i = 0; i < nfe; i++) 01764 if (!wsd || ufes->GetAttribute(i) == s) 01765 { 01766 ufes->GetElementVDofs(i, udofs); 01767 ffes->GetElementVDofs(i, fdofs); 01768 01769 ul.SetSize(udofs.Size()); 01770 for (j = 0; j < ul.Size(); j++) 01771 ul(j) = u(udofs[j]); 01772 01773 fla.SetSize(fdofs.Size()); 01774 for (j = 0; j < fla.Size(); j++) 01775 fla(j) = flux(fdofs[j]); 01776 01777 Transf = ufes->GetElementTransformation(i); 01778 blfi.ComputeElementFlux(*ufes->GetFE(i), *Transf, ul, 01779 *ffes->GetFE(i), fl, 0); 01780 01781 fl -= fla; 01782 01783 ErrorEstimates(i) = blfi.ComputeFluxEnergy(*ffes->GetFE(i), 01784 *Transf, fl); 01785 } 01786 } 01787 }