MFEM v2.0
gridfunc.cpp
Go to the documentation of this file.
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 }
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Defines