#include #include namespace ngcomp { using namespace ngcomp; using namespace ngmg; GridFunction :: GridFunction (const FESpace & afespace, const string & name, const Flags & flags) : NGS_Object (afespace.GetMeshAccess(), name), fespace(afespace) { nested = flags.GetDefineFlag ("nested"); visual = !flags.GetDefineFlag ("novisual"); multidim = int (flags.GetNumFlag ("multidim", 1)); level_updated = -1; } void GridFunction :: PrintReport (ostream & ost) { ost << "on space " << GetFESpace().GetName() << endl << "nested = " << nested << endl; } void GridFunction :: MemoryUsage (ARRAY & mu) const { if (&const_cast (*this).GetVector()) { int olds = mu.Size(); const_cast (*this).GetVector().MemoryUsage (mu); for (int i = olds; i < mu.Size(); i++) mu[i]->AddName (string(" gf ")+GetName()); } } void GridFunction :: Visualize(const string & name) { cout << "visualize gridfunction " << name << endl; if (!visual) return; // new version: const BilinearFormIntegrator *bfi2d = 0, *bfi3d = 0; netgen::SolutionData * vis; if (ma.GetDimension() == 2) { bfi2d = fespace.GetEvaluator(); } else { bfi3d = fespace.GetEvaluator(); bfi2d = fespace.GetBoundaryEvaluator(); } if (bfi2d || bfi3d) { // if (ma.GetNLevels() > 1) return; if (!fespace.IsComplex()) vis = new VisualizeGridFunction (ma, this, bfi2d, bfi3d, 0); else vis = new VisualizeGridFunction (ma, this, bfi2d, bfi3d, 0); Ng_SolutionData soldata; Ng_InitSolutionData (&soldata); soldata.name = const_cast (GetName().c_str()); soldata.data = 0; soldata.components = vis->GetComponents(); soldata.iscomplex = vis->IsComplex(); soldata.draw_surface = bfi2d != 0; soldata.draw_volume = bfi3d != 0; soldata.dist = soldata.components; soldata.soltype = NG_SOLUTION_VIRTUAL_FUNCTION; soldata.solclass = vis; Ng_SetSolutionData (&soldata); } /* const MeshAccess & ma = GetMeshAccess(); Ng_SolutionData soldata; Ng_InitSolutionData (&soldata); soldata.name = const_cast (name.c_str()); if (&GetVector()) { FlatVector<> fv = GetVector().FVDouble(); soldata.data = &fv[0]; if (!GetFESpace().IsComplex()) soldata.components = GetFESpace().GetDimension(); else soldata.components = 2*GetFESpace().GetDimension(); // soldata.data = static_cast (GetVector().Data()); // soldata.components = GetVector().ElementSize() / sizeof (double); } else { soldata.data = 0; soldata.components = 1; } soldata.dist = soldata.components; soldata.soltype = NG_SOLUTION_NODAL; soldata.order = GetFESpace().GetOrder(); soldata.iscomplex = GetFESpace().IsComplex(); if (dynamic_cast (&GetFESpace())) { ; } else if (dynamic_cast (&GetFESpace())) { if (ma.GetDimension() == 3) { if (GetFESpace().GetOrder() == 0) soldata.soltype = NG_SOLUTION_ELEMENT; else soldata.soltype = NG_SOLUTION_NONCONTINUOUS; } else { if (GetFESpace().GetOrder() == 0) soldata.soltype = NG_SOLUTION_SURFACE_ELEMENT; else soldata.soltype = NG_SOLUTION_SURFACE_NONCONTINUOUS; } } else if (dynamic_cast (&GetFESpace())) { if (ma.GetDimension() == 3) { if (GetFESpace().GetOrder() == 0) soldata.soltype = NG_SOLUTION_SURFACE_ELEMENT; else soldata.soltype = NG_SOLUTION_SURFACE_NONCONTINUOUS; } } else if (dynamic_cast (&GetFESpace()) || dynamic_cast (&GetFESpace()) || dynamic_cast (&GetFESpace()) ) { // do not visualize, and do not complain return; } else { // throw Exception ("Don't know how to visualize gridfunction in fespace" + // GetFESpace().GetClassName()); cout << "Don't know how to visualize gridfunction in fespace" << endl; } Ng_SetSolutionData (&soldata); */ } template T_GridFunction :: T_GridFunction (const FESpace & afespace, const string & aname, const Flags & flags) : S_GridFunction (afespace, aname, flags), vec(0) { vec.SetSize (this->multidim); vec = 0; Visualize (this->name); } template T_GridFunction :: ~T_GridFunction() { for (int i = 0; i < vec.Size(); i++) delete vec[i]; } template void T_GridFunction :: Update () { try { NgLock lock(this -> mutex, 1); int ndof = this->GetFESpace().GetNDof(); // cout << "update gridfunction, ndof = " << ndof << endl; for (int i = 0; i < this->multidim; i++) { if (vec[i] && ndof == vec[i]->Size()) break; ngla::VVector * ovec = vec[i]; vec[i] = new VVector (ndof); if (this->nested && ovec && this->GetFESpace().GetProlongation()) { (*vec[i]) = TSCAL(0); *vec[i]->Range (0, ovec->Size()) += (*ovec); const_cast (*this->GetFESpace().GetProlongation()).Update(); cout << "prolongate gridfunction" << endl; this->GetFESpace().GetProlongation()->ProlongateInline (this->GetMeshAccess().GetNLevels()-1, *vec[i]); } else { (*vec[i]) = TSCAL(0); // cout << "do not prolongate gridfunction" << endl; } // if (i == 0) // cout << "visualize" << endl; Visualize (this->name); if (ovec) delete ovec; } this -> level_updated = this -> ma.GetNLevels(); } catch (exception & e) { Exception e2 (e.what()); e2.Append ("\nIn GridFunction::Update()\n"); throw e2; } catch (Exception & e) { e.Append ("In GridFunction::Update()\n"); throw e; } } template BaseVector & T_GridFunction :: GetVector (int comp) { return *vec[comp]; } /// template void T_GridFunction :: GetElementVector (const ARRAY & dnums, FlatVector & elvec) const { FlatVector fv = vec[0]->FV(); for (int k = 0; k < dnums.Size(); k++) if (dnums[k] != -1) for (int j = 0; j < VDIM; j++) // elvec(k*VDIM+j) = fv(dnums[k])(j); elvec(k*VDIM+j) = Access (fv(dnums[k]),j); else for (int j = 0; j < VDIM; j++) elvec(k*VDIM+j) = 0; } /// template void T_GridFunction :: SetElementVector (const ARRAY & dnums, const FlatVector & elvec) { FlatVector fv = vec[0]->FV(); for (int k = 0; k < dnums.Size(); k++) if (dnums[k] != -1) for (int j = 0; j < VDIM; j++) // fv(dnums[k])(j) = elvec(k*VDIM+j); Access (fv(dnums[k]),j) = elvec(k*VDIM+j); } template void T_GridFunction :: GetElementVector (int comp, const ARRAY & dnums, FlatVector & elvec) const { if (comp < 0 || comp >= vec.Size()) { cout << "multidim-component out of range" << endl; elvec = 0; return; } FlatVector fv = vec[comp]->FV(); for (int k = 0; k < dnums.Size(); k++) if (dnums[k] != -1) for (int j = 0; j < VDIM; j++) // elvec(k*VDIM+j) = fv(dnums[k])(j); elvec(k*VDIM+j) = Access (fv(dnums[k]),j); else for (int j = 0; j < VDIM; j++) elvec(k*VDIM+j) = 0; } /// template void T_GridFunction :: SetElementVector (int comp, const ARRAY & dnums, const FlatVector & elvec) { FlatVector fv = vec[comp]->FV(); for (int k = 0; k < dnums.Size(); k++) if (dnums[k] != -1) for (int j = 0; j < VDIM; j++) // fv(dnums[k])(j) = elvec(k*VDIM+j); Access (fv(dnums[k]),j) = elvec(k*VDIM+j); } /* /// template <> void T_GridFunction:: GetElementVector (const ARRAY & dnums, FlatVector & elvec) const { FlatVector fv = vec->FV(); for (int k = 0; k < dnums.Size(); k++) if (dnums[k] != -1) elvec(k) = fv(dnums[k]); else elvec(k) = 0; } /// template <> void T_GridFunction:: SetElementVector (const ARRAY & dnums, const FlatVector & elvec) { FlatVector fv = vec->FV(); for (int k = 0; k < dnums.Size(); k++) if (dnums[k] != -1) fv(dnums[k]) = elvec(k); } template <> void T_GridFunction:: GetElementVector (const ARRAY & dnums, FlatVector & elvec) const { FlatVector fv = vec->FV(); for (int k = 0; k < dnums.Size(); k++) if (dnums[k] != -1) elvec(k) = fv(dnums[k]); else elvec(k) = 0; } /// template <> void T_GridFunction:: SetElementVector (const ARRAY & dnums, const FlatVector & elvec) { FlatVector fv = vec->FV(); for (int k = 0; k < dnums.Size(); k++) if (dnums[k] != -1) fv(dnums[k]) = elvec(k); } */ GridFunction * CreateGridFunction (const FESpace * space, const string & name, const Flags & flags) { /* GridFunction * gf; CreateVecObject3 (gf, T_GridFunction, space->GetDimension(), space->IsComplex(), *space, name, flags); return gf; */ return CreateVecObject (space->GetDimension(), space->IsComplex(), *space, name, flags); } /* class GridFunctionCoefficientFunction : public CoefficientFunction { int GridFunction * gf; int comp; public: */ GridFunctionCoefficientFunction :: GridFunctionCoefficientFunction (T_GridFunction & agf) : gf(agf) { ; } GridFunctionCoefficientFunction :: ~GridFunctionCoefficientFunction () { ; } template VisualizeGridFunction :: VisualizeGridFunction (const MeshAccess & ama, const GridFunction * agf, const BilinearFormIntegrator * abfi2d, const BilinearFormIntegrator * abfi3d, bool aapplyd) : SolutionData (agf->GetName(), -1, agf->GetFESpace().IsComplex()), ma(ama), gf(dynamic_cast*> (agf)), bfi2d(abfi2d), bfi3d(abfi3d), applyd(aapplyd), cache_elnr(-1), lh(1000000) { if (bfi2d) components = bfi2d->DimFlux(); if (bfi3d) components = bfi3d->DimFlux(); if (iscomplex) components *= 2; multidimcomponent = 0; } template VisualizeGridFunction :: ~VisualizeGridFunction () { ; } template bool VisualizeGridFunction :: GetValue (int elnr, double lam1, double lam2, double lam3, double * values) { if (!bfi3d) return 0; if (gf -> GetLevelUpdated() < ma.GetNLevels()) return 0; LocalHeapMem<10000> lh2; const FESpace & fes = gf->GetFESpace(); const FiniteElement & fel = fes.GetFE (elnr, lh2); int dim = fes.GetDimension(); NgLock lock(const_cast*> (gf) -> Mutex(), 1); // added 07.04.2004 (FB): don't draw, if not defined on this domain if ( !fes.DefinedOn(ma.GetElIndex(elnr)) ) return 0; if (cache_elnr != elnr || cache_bound) { lh.CleanUp(); ma.GetElementTransformation (elnr, eltrans, lh); fes.GetDofNrs (elnr, dnums); elu.AssignMemory (dnums.Size() * dim, lh); gf->GetElementVector (multidimcomponent, dnums, elu); fes.TransformVec (elnr, 0, elu, TRANSFORM_SOL); cache_elnr = elnr; cache_bound = 0; } void * hp = lh.GetPointer(); FlatVector flux; IntegrationPoint ip(lam1, lam2, lam3, 0); bfi3d->CalcFlux (fel, eltrans, ip, elu, flux, applyd, lh); for (int i = 0; i < components; i++) values[i] = ((double*)(void*)&flux(0))[i]; lh.CleanUp(hp); return 1; } template bool VisualizeGridFunction :: GetSurfValue (int elnr, double lam1, double lam2, double * values) { if (!bfi2d) return 0; if (gf -> GetLevelUpdated() < ma.GetNLevels()) return 0; bool bound = (ma.GetDimension() == 3); const FESpace & fes = gf->GetFESpace(); LocalHeapMem<10000> lh2; NgLock lock(const_cast*> (gf) -> Mutex(), 1); const FiniteElement & fel = bound ? fes.GetSFE(elnr, lh2) : fes.GetFE (elnr, lh2); int dim = fes.GetDimension(); // added 07.04.2004 (FB): don't draw, if not defined on this domain if ( bound ? !fes.DefinedOnBoundary(ma.GetSElIndex(elnr)) : !fes.DefinedOn(ma.GetElIndex(elnr)) ) return 0; if (cache_elnr != elnr || !cache_bound) { lh.CleanUp(); if (bound) { ma.GetSurfaceElementTransformation (elnr, eltrans, lh); fes.GetSDofNrs (elnr, dnums); } else { ma.GetElementTransformation (elnr, eltrans, lh); fes.GetDofNrs (elnr, dnums); } elu.AssignMemory (dnums.Size() * dim, lh); gf->GetElementVector (multidimcomponent, dnums, elu); fes.TransformVec (elnr, bound, elu, TRANSFORM_SOL); cache_elnr = elnr; cache_bound = 1; } void * hp = lh.GetPointer(); FlatVector flux; IntegrationPoint ip(lam1, lam2, 0, 0); // bfi2d->CalcFlux (fel, eltrans, ip, elu, flux, applyd, lh); if (bound) { SpecificIntegrationPoint<2,3> sip (ip, eltrans, lh); bfi2d->CalcFlux (fel, sip, elu, flux, applyd, lh); } else { SpecificIntegrationPoint<2,2> sip (ip, eltrans, lh); bfi2d->CalcFlux (fel, sip, elu, flux, applyd, lh); } for (int i = 0; i < components; i++) values[i] = ((double*)(void*)&flux(0))[i]; lh.CleanUp(hp); return 1; } template void VisualizeGridFunction :: Analyze(ARRAY & minima, ARRAY & maxima, ARRAY & averages, int component) { int ndomains; if(bfi3d) ndomains = ma.GetNDomains(); else if(bfi2d) ndomains = ma.GetNBoundaries(); ARRAY volumes(ndomains); Analyze(minima,maxima,averages,volumes,component); for(int i=0; i void VisualizeGridFunction :: Analyze(ARRAY & minima, ARRAY & maxima, ARRAY & averages_times_volumes, ARRAY & volumes, int component) { const FESpace & fes = gf->GetFESpace(); int domain; double *val; int pos; double vol; int ndomains; if(bfi3d) ndomains = ma.GetNDomains(); else if(bfi2d) ndomains = ma.GetNBoundaries(); ARRAY posx; ARRAY posy; ARRAY posz; ELEMENT_TYPE cache_type = ET_SEGM; LocalHeapMem<10000> lh2; val = new double[components]; for(int i=0; i maxima[pos]) maxima[pos] = val[j]; if(val[j] < minima[pos]) minima[pos] = val[j]; if(k==0) averages_times_volumes[pos] += val[j]*vol; } } else { pos = domain; if(val[component] > maxima[pos]) maxima[pos] = val[component]; if(val[component] < minima[pos]) minima[pos] = val[component]; if(k==0) averages_times_volumes[pos] += val[component]*vol; } } lh2.CleanUp(heapp); } } else if (bfi2d) { for(int i=0; i maxima[pos]) maxima[pos] = val[j]; if(val[j] < minima[pos]) minima[pos] = val[j]; if(k==0) averages_times_volumes[pos] += val[j]*vol; } } else { pos = domain; if(val[component] > maxima[pos]) maxima[pos] = val[component]; if(val[component] < minima[pos]) minima[pos] = val[component]; if(k==0) averages_times_volumes[pos] += val[component]*vol; } } lh2.CleanUp(heapp); } } delete [] val; } template class VisualizeGridFunction; template class VisualizeGridFunction; }