| 276 | } |
| 277 | |
| 278 | vector<string> GenerateVolumeData( shared_ptr<MeshAccess> ma, |
| 279 | shared_ptr<CoefficientFunction> cf, |
| 280 | int order) { |
| 281 | LocalHeapMem<100000> lh("webgui_volume_data"); |
| 282 | Array<double> volume_data; |
| 283 | auto comps = cf->Dimension(); |
| 284 | for (auto elnr : Range(ma->GetNElements(3))) { |
| 285 | HeapReset hr(lh); |
| 286 | |
| 287 | auto el = ma->GetElement({VOL, elnr}); |
| 288 | auto &ir = GetElementPoints(el.GetType(), order); |
| 289 | auto &trafo = ma->GetTrafo(el, lh); |
| 290 | BaseMappedIntegrationRule &mir = trafo(ir, lh); |
| 291 | FlatMatrix<> values(ir.Size(), comps, lh); |
| 292 | cf->Evaluate(mir, values); |
| 293 | volume_data.Append( |
| 294 | FlatArray<double>(values.AsVector().Size(), values.Data())); |
| 295 | } |
| 296 | auto nip = GetElementPoints(ET_TET, order).Size(); |
| 297 | auto nel = volume_data.Size() / nip / |
| 298 | comps; // might be different from ma->GetNElements(3), because |
| 299 | // hexes/prisms are divided into tets |
| 300 | FlatTensor<3, double> data(nel, nip, comps, volume_data.Data()); |
| 301 | Tensor<3, double> output(nip, nel, comps); |
| 302 | |
| 303 | for (size_t i = 0; i < nel; i++) |
| 304 | output(STAR, i, STAR) = data(i, STAR, STAR); |
| 305 | |
| 306 | Tensor<3, float> output_f(nip, nel, comps); |
| 307 | auto n = output.GetTotalSize(); |
| 308 | for (auto i : Range(n)) output_f.Data()[i] = output.Data()[i]; |
| 309 | |
| 310 | std::vector<string> ret; |
| 311 | for (auto i : Range(nip)) { |
| 312 | auto vals = output_f(i, STAR, STAR); |
| 313 | ret.push_back(base64_encode(FlatArray<unsigned char>( |
| 314 | vals.Height() * vals.Width() * sizeof(vals(0, 0)), |
| 315 | reinterpret_cast<unsigned char *>(vals.Data())))); |
| 316 | } |
| 317 | return ret; |
| 318 | } |
| 319 | |
| 320 | unique_ptr<WebguiData> GenerateWebguiData(shared_ptr<MeshAccess> ma, |
| 321 | shared_ptr<CoefficientFunction> cf, |
no test coverage detected