11 #include "SampleMesh.hpp"
20 #define FULL_DOF_STENCIL
22 void FindStencilElements(
const vector<int>& sample_dofs_gid,
24 ParFiniteElementSpace& fespace)
26 for (
int k = 0; k < fespace.GetParMesh()->GetNE(); k++)
29 fespace.GetElementVDofs(k, dofs);
31 for (vector<int>::const_iterator it = sample_dofs_gid.begin();
32 it != sample_dofs_gid.end(); ++it)
34 for (
int i = 0; i < dofs.Size(); i++)
36 const int dof_i = dofs[i] >= 0 ? dofs[i] : -1 - dofs[i];
37 int global_dof = fespace.GetGlobalTDofNumber(dof_i);
38 if (global_dof == *it)
50 void FindSampledMeshEntities(
const int type,
const vector<int>& sample_dofs_gid,
51 set<int>& entities, ParFiniteElementSpace& fespace)
57 N = fespace.GetParMesh()->GetNE();
60 N = fespace.GetParMesh()->GetNFaces();
63 N = fespace.GetParMesh()->GetNEdges();
66 N = fespace.GetParMesh()->GetNV();
70 for (
int k = 0; k < N; k++)
77 fespace.GetElementInteriorVDofs(k, dofs);
80 fespace.GetFaceVDofs(k, dofs);
83 fespace.GetEdgeVDofs(k, dofs);
86 fespace.GetVertexVDofs(k, dofs);
90 for (vector<int>::const_iterator it = sample_dofs_gid.begin();
91 it != sample_dofs_gid.end(); ++it)
93 for (
int i = 0; i < dofs.Size(); i++)
95 const int dof_i = dofs[i] >= 0 ? dofs[i] : -1 - dofs[i];
96 int global_dof = fespace.GetGlobalTDofNumber(dof_i);
97 if (global_dof == *it)
110 void GetLocalSampleMeshElements(ParMesh& pmesh, ParFiniteElementSpace& fespace,
111 const vector<int>& sample_dofs,
112 const vector<int>& local_num_sample_dofs, set<int>& elems,
113 bool getSampledEntities, set<int>& intElems, set<int>& faces, set<int>& edges,
117 MPI_Comm_rank(MPI_COMM_WORLD, &myid);
118 const int num_procs = local_num_sample_dofs.size();
121 map<int, int> ltdof2gtdof;
122 const int ndofs = fespace.GetVSize();
123 for (
int i = 0; i < fespace.GetVSize(); ++i) {
124 int ltdof = fespace.GetLocalTDofNumber(i);
127 int gtdof = fespace.GetGlobalTDofNumber(i);
128 ltdof2gtdof[ltdof] = gtdof;
133 int* offsets =
new int [num_procs];
135 for (
int i = 1; i < num_procs; ++i) {
136 offsets[i] = offsets[i-1] + local_num_sample_dofs[i-1];
139 vector<int> local_sample_dofs_gid;
140 int my_offset = offsets[myid];
141 for (
int i = 0; i < local_num_sample_dofs[myid]; ++i) {
142 map<int, int>::const_iterator it = ltdof2gtdof.find(sample_dofs[my_offset+i]);
143 MFEM_VERIFY(it != ltdof2gtdof.end(),
"");
144 local_sample_dofs_gid.push_back(ltdof2gtdof[sample_dofs[my_offset+i]]);
147 int total_num_sample_dofs =
static_cast<int>(sample_dofs.size());
148 vector<int> sample_dofs_gid(total_num_sample_dofs);
149 MPI_Allgatherv(&local_sample_dofs_gid[0], local_num_sample_dofs[myid],
150 MPI_INT, &sample_dofs_gid[0], &local_num_sample_dofs[0],
151 offsets, MPI_INT, MPI_COMM_WORLD);
156 FindStencilElements(sample_dofs_gid, elems, fespace);
158 if (getSampledEntities)
160 FindSampledMeshEntities(0, sample_dofs_gid, intElems, fespace);
161 if (fespace.GetParMesh()->Dimension() == 3) FindSampledMeshEntities(1,
162 sample_dofs_gid, faces, fespace);
163 FindSampledMeshEntities(2, sample_dofs_gid, edges, fespace);
164 FindSampledMeshEntities(3, sample_dofs_gid, vertices, fespace);
170 void SplitDofsIntoBlocks(
const vector<int>& Ntrue,
const vector<int>& dofs,
171 const vector<int>& local_num_dofs,
172 vector<vector<int>>& dofs_block, vector<vector<int>>& dofs_block_todofs,
173 vector<vector<int>>& local_num_dofs_block)
175 const int num_procs = local_num_dofs.size();
176 const int nspaces = Ntrue.size();
178 MFEM_VERIFY(nspaces > 0 && nspaces == dofs_block.size()
179 && nspaces == dofs_block_todofs.size()
180 && nspaces == local_num_dofs_block.size(),
"");
182 vector<vector<vector<int>>> procDofs_block(nspaces);
183 vector<vector<int>> allNtrue(nspaces);
185 for (
int i=0; i<nspaces; ++i)
187 local_num_dofs_block[i].resize(num_procs);
188 local_num_dofs_block[i].assign(local_num_dofs_block[i].size(), 0);
189 procDofs_block[i].resize(num_procs);
191 allNtrue[i].resize(num_procs);
192 MPI_Allgather(&Ntrue[i], 1, MPI_INT, allNtrue[i].data(), 1, MPI_INT,
196 vector<int> spaceOS(nspaces);
200 vector<int>::const_iterator it = dofs.begin();
201 for (
int p=0; p<num_procs; ++p)
203 for (
int i=1; i<nspaces; ++i)
205 spaceOS[i] = spaceOS[i-1] + allNtrue[i-1][p];
208 for (
int i=0; i<local_num_dofs[p]; ++i, ++it)
211 for (
int s=nspaces-1; s>=0; --s)
213 if (*it >= spaceOS[s])
215 dofs_block[s].push_back(*it - spaceOS[s]);
216 dofs_block_todofs[s].push_back(os + i);
217 local_num_dofs_block[s][p]++;
222 MFEM_VERIFY(found,
"Space not found");
225 os += local_num_dofs[p];
228 MFEM_VERIFY(it == dofs.end(),
"");
231 void InsertElementDofs(ParFiniteElementSpace& fespace,
const int elId,
232 const int offset, set<int>& element_dofs)
235 fespace.GetElementVDofs(elId, dofs);
236 for (
int i = 0; i < dofs.Size(); ++i) {
237 const int dof_i = dofs[i] >= 0 ? dofs[i] : -1 - dofs[i];
238 #ifdef FULL_DOF_STENCIL
239 element_dofs.insert(offset + dof_i);
241 int ltdof = fespace.GetLocalTDofNumber(dof_i);
243 element_dofs.insert(offset + ltdof);
250 void AugmentDofListWithOwnedDofs(vector<int>& mixedDofs,
251 vector<ParFiniteElementSpace*> & fespace)
253 const int nspaces = fespace.size();
254 vector<int> spaceOS(nspaces);
257 for (
int i=1; i<nspaces; ++i)
258 spaceOS[i] = spaceOS[i-1] + fespace[i-1]->GetVSize();
260 vector<vector<int> > dofs(nspaces);
261 set<int> mixedDofSet;
262 for (
auto i : mixedDofs)
264 mixedDofSet.insert(i);
267 for (
int j=nspaces-1; j > 0; --j)
276 dofs[space].push_back(i - spaceOS[space]);
280 MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
282 vector<int> cts(nprocs);
283 vector<int> offsets(nprocs);
285 for (
int s=0; s<nspaces; ++s)
287 const int ndofs = dofs[s].size();
288 MPI_Allgather(&ndofs, 1, MPI_INT, cts.data(), 1, MPI_INT, MPI_COMM_WORLD);
291 for (
int i = 1; i < nprocs; ++i)
292 offsets[i] = offsets[i-1] + cts[i-1];
294 vector<int> gdofs(ndofs);
295 for (
int i = 0; i<ndofs; ++i)
297 gdofs[i] = fespace[s]->GetGlobalTDofNumber(dofs[s][i]);
300 vector<int> gdofsGathered(offsets[nprocs-1] + cts[nprocs-1]);
302 MPI_Allgatherv(gdofs.data(), ndofs, MPI_INT,
303 gdofsGathered.data(), cts.data(), offsets.data(), MPI_INT, MPI_COMM_WORLD);
307 for (
auto i : gdofsGathered)
310 for (
int i=0; i<fespace[s]->GetVSize(); ++i)
312 int ltdof = fespace[s]->GetLocalTDofNumber(i);
315 const int g = fespace[s]->GetGlobalTDofNumber(i);
316 set<int>::iterator it = allgdofs.find(g);
317 if (it != allgdofs.end())
320 const int j = spaceOS[s] + i;
321 set<int>::iterator it = mixedDofSet.find(j);
322 if (it == mixedDofSet.end())
324 mixedDofs.push_back(j);
325 mixedDofSet.insert(j);
333 void BuildSampleMesh(ParMesh& pmesh, vector<ParFiniteElementSpace*> & fespace,
334 const set<int>& elems, Mesh*& sample_mesh, vector<int>& stencil_dofs,
335 vector<int>& elemLocalIndices, vector<map<int, int> >& elemLocalIndicesInverse)
340 MPI_Comm_size(MPI_COMM_WORLD, &num_procs);
342 const int d = pmesh.Dimension();
345 H1_FECollection h1_coll(1, d);
348 ParFiniteElementSpace H1DummySpace(&pmesh, &h1_coll);
350 vector<int> procNumElems(num_procs);
352 const int local_num_elems = elems.size();
353 int* cts =
new int [num_procs];
354 int* offsets =
new int [num_procs];
355 MPI_Allgather(&local_num_elems, 1, MPI_INT, cts, 1, MPI_INT, MPI_COMM_WORLD);
356 int sample_mesh_num_elems = 0;
358 for (
int i = 0; i < num_procs; ++i) {
359 sample_mesh_num_elems += cts[i];
360 procNumElems[i] = cts[i];
363 offsets[i] = offsets[i-1] + cts[i-1];
366 const int nspaces = fespace.size();
368 vector<int> spaceN(nspaces);
369 for (
int i=0; i<nspaces; ++i)
371 #ifdef FULL_DOF_STENCIL
372 spaceN[i] = fespace[i]->GetVSize();
374 spaceN[i] = fespace[i]->TrueVSize();
385 vector<int> my_element_attr(
387 set<int> element_dofs;
392 pmesh.GetElementVertices(*elems.begin(), elVert);
393 int numElVert = elVert.Size();
394 MFEM_VERIFY(numElVert > 0,
"");
397 vector<int> my_element_vgid(numElVert*local_num_elems);
398 vector<double> my_element_coords(d*numElVert*local_num_elems);
400 for (set<int>::iterator it = elems.begin(); it != elems.end(); ++it) {
401 const int elId = *it;
403 for (
int i=0; i<nspaces; ++i)
405 InsertElementDofs(*fespace[i], elId, os, element_dofs);
409 pmesh.GetElementVertices(elId, elVert);
410 MFEM_VERIFY(numElVert == elVert.Size(),
411 "Assuming a uniform element type in the mesh.");
415 H1DummySpace.GetElementDofs(elId, dofs);
416 MFEM_VERIFY(numElVert == dofs.Size(),
417 "Assuming a bijection between vertices and H1 dummy space DOF's");
419 for (
int i = 0; i < numElVert; ++i) {
420 my_element_vgid[conn_idx++] = H1DummySpace.GetGlobalTDofNumber(dofs[i]);
421 double* coords = pmesh.GetVertex(elVert[i]);
422 for (
int j=0; j<d; ++j)
423 my_element_coords[coords_idx++] = coords[j];
426 my_element_attr[attr_idx++] = pmesh.GetAttribute(elId);
427 my_element_attr[attr_idx++] = elId;
430 stencil_dofs.assign(element_dofs.begin(), element_dofs.end());
432 #ifdef FULL_DOF_STENCIL
433 AugmentDofListWithOwnedDofs(stencil_dofs, fespace);
436 MFEM_VERIFY(coords_idx == d*numElVert*local_num_elems,
"");
437 MFEM_VERIFY(conn_idx == numElVert*local_num_elems,
"");
438 MFEM_VERIFY(attr_idx == 2*local_num_elems,
"");
442 vector<int> element_attr(2*sample_mesh_num_elems);
443 MPI_Allgatherv(&my_element_attr[0], 2*local_num_elems, MPI_INT,
444 &element_attr[0], cts, offsets, MPI_INT, MPI_COMM_WORLD);
448 cts[0] = numElVert*cts[0]/2;
449 for (
int i = 1; i < num_procs; ++i) {
450 cts[i] = numElVert*cts[i]/2;
451 offsets[i] = offsets[i-1] + cts[i-1];
453 vector<int> element_vgid(numElVert*sample_mesh_num_elems);
454 MPI_Allgatherv(&my_element_vgid[0], numElVert*local_num_elems, MPI_INT,
455 &element_vgid[0], cts, offsets, MPI_INT, MPI_COMM_WORLD);
460 for (
int i = 1; i < num_procs; ++i) {
462 offsets[i] = offsets[i-1] + cts[i-1];
464 vector<double> element_coords(d*numElVert*sample_mesh_num_elems);
465 MPI_Allgatherv(&my_element_coords[0], d*numElVert*local_num_elems, MPI_DOUBLE,
466 &element_coords[0], cts, offsets, MPI_DOUBLE, MPI_COMM_WORLD);
475 set<int> unique_gdofs;
476 map<int, int> unique_gdofs_first_appearance;
477 for (
int i = 0; i < numElVert*sample_mesh_num_elems; ++i) {
478 int gdof = element_vgid[i];
479 if (unique_gdofs.insert(gdof).second) {
480 unique_gdofs_first_appearance.insert(make_pair(gdof, i));
483 int sample_mesh_num_verts = unique_gdofs.size();
484 map<int, int> unique_gdofs_2_vertex;
485 map<int, int> vertex_2_unique_gdofs;
487 for (set<int>::iterator it = unique_gdofs.begin();
488 it != unique_gdofs.end(); ++it) {
489 unique_gdofs_2_vertex.insert(make_pair(*it, idx));
490 vertex_2_unique_gdofs.insert(make_pair(idx, *it));
495 printf(
"sample mesh has %d elements, %d vertices\n",
496 sample_mesh_num_elems, sample_mesh_num_verts);
498 sample_mesh =
new Mesh(d, sample_mesh_num_verts, sample_mesh_num_elems);
501 for (
int vert = 0; vert < sample_mesh_num_verts; ++vert) {
502 int unique_gdof = vertex_2_unique_gdofs[vert];
503 int first_conn_ref = unique_gdofs_first_appearance[unique_gdof];
504 int coord_loc = d*first_conn_ref;
505 sample_mesh->AddVertex(&element_coords[coord_loc]);
509 const int elGeom = pmesh.GetElementBaseGeometry(0);
511 elemLocalIndices.resize(sample_mesh_num_elems);
512 elemLocalIndicesInverse.resize(num_procs);
514 for (
int p=0; p<num_procs; ++p)
516 for (
int i=0; i<procNumElems[p]; ++i, ++ielem)
518 Element* sel = sample_mesh->NewElement(elGeom);
519 sel->SetAttribute(element_attr[2*ielem]);
521 elemLocalIndices[ielem] = element_attr[(2*ielem)+1];
522 elemLocalIndicesInverse[p][elemLocalIndices[ielem]] = ielem;
524 Array<int> sv(numElVert);
525 for (
int vert = 0; vert < numElVert; ++vert) {
526 sv[vert] = unique_gdofs_2_vertex[element_vgid[idx++]];
528 sel->SetVertices(sv);
530 sample_mesh->AddElement(sel);
534 MFEM_VERIFY(ielem == sample_mesh_num_elems,
"");
536 sample_mesh->FinalizeTopology();
539 void GetLocalDofsToLocalElementMap(ParFiniteElementSpace& fespace,
540 const vector<int>& dofs,
541 const vector<int>& localNumDofs,
542 const set<int>& elems,
543 vector<int>& dofToElem,
544 vector<int>& dofToElemDof,
548 MPI_Comm_rank(MPI_COMM_WORLD, &myid);
551 for (
int p=0; p<myid; ++p)
552 myoffset += localNumDofs[p];
554 dofToElem.resize(localNumDofs[myid]);
555 dofToElemDof.resize(localNumDofs[myid]);
559 for (
int i=0; i<localNumDofs[myid]; ++i)
562 for (set<int>::const_iterator it = elems.begin(); it != elems.end(); ++it)
564 const int elId = *it;
565 fespace.GetElementVDofs(elId, eldofs);
567 for (
int j=0; j<eldofs.Size(); ++j)
569 const int eldof_j = eldofs[j] >= 0 ? eldofs[j] : -1 - eldofs[j];
570 int ltdof = fespace.GetLocalTDofNumber(eldof_j);
571 #ifdef FULL_DOF_STENCIL
572 const int dof_j = useTDof ? ltdof : eldof_j;
573 if (dof_j == dofs[myoffset + i])
575 if (ltdof == dofs[myoffset + i])
586 #ifndef FULL_DOF_STENCIL
587 const int dte = dofToElem[i];
588 MFEM_VERIFY(dofToElem[i] >= 0,
"");
593 void Set_s2sp(
const int myid,
const int num_procs, vector<int>
const& spNtrue,
594 const int global_num_sample_dofs,
const vector<int>& local_num_sample_dofs,
595 const vector<vector<int> >& local_num_sample_dofs_sub,
596 const vector<vector<int> >& localSampleDofsToElem_sub,
597 const vector<vector<int> >& localSampleDofsToElemDof_sub,
598 const vector<vector<int> >& sample_dofs_sub_to_sample_dofs,
599 const vector<map<int, int> >& elemLocalIndicesInverse,
600 vector<ParFiniteElementSpace*> & spfespace,
617 const int nspaces = spfespace.size();
618 MFEM_VERIFY(nspaces == spNtrue.size(),
"");
620 int mySampleDofOffset = 0;
622 os.assign(nspaces, 0);
623 for (
int p=0; p<myid; ++p)
625 mySampleDofOffset += local_num_sample_dofs[p];
626 for (
int i=0; i<nspaces; ++i)
627 os[i] += local_num_sample_dofs_sub[i][p];
631 vector<int> mySampleToElement(2*local_num_sample_dofs[myid]);
634 mySampleToElement.assign(mySampleToElement.size(), -1);
636 for (
int s=0; s<nspaces; ++s)
638 for (
int i=0; i<local_num_sample_dofs_sub[s][myid]; ++i)
640 const int sdi = sample_dofs_sub_to_sample_dofs[s][os[s] + i] -
642 mySampleToElement[2*sdi] = localSampleDofsToElem_sub[s][i];
643 mySampleToElement[(2*sdi)+1] = localSampleDofsToElemDof_sub[s][i];
647 #ifndef FULL_DOF_STENCIL
648 for (
int i=0; i<mySampleToElement.size(); ++i)
650 MFEM_VERIFY(mySampleToElement[i] >= 0,
"");
654 int* cts =
new int [num_procs];
655 int* offsets =
new int [num_procs];
658 cts[0] = 2*local_num_sample_dofs[0];
659 for (
int i = 1; i < num_procs; ++i) {
660 cts[i] = 2*local_num_sample_dofs[i];
661 offsets[i] = offsets[i-1] + cts[i-1];
666 vector<int> sampleToElement(2*global_num_sample_dofs);
667 MPI_Allgatherv(&mySampleToElement[0], 2*local_num_sample_dofs[myid], MPI_INT,
668 &sampleToElement[0], cts, offsets, MPI_INT, MPI_COMM_WORLD);
677 vector<int> spaceOS(nspaces);
680 for (
int i=1; i<nspaces; ++i)
681 spaceOS[i] = spaceOS[i-1] + spfespace[i-1]->GetVSize();
683 s2sp.resize(global_num_sample_dofs);
685 s2sp.assign(s2sp.size(), -1);
687 for (
int s=0; s<nspaces; ++s)
692 for (
int p=0; p<num_procs; ++p)
694 for (
int s=0; s<nspaces; ++s)
696 for (
int i=0; i<local_num_sample_dofs_sub[s][p]; ++i)
698 const int sdi = sample_dofs_sub_to_sample_dofs[s][os[s] + i];
699 const int procElementIndex = sampleToElement[2*sdi];
700 #ifdef FULL_DOF_STENCIL
701 if (procElementIndex == -1)
704 const int procElementDofIndex = sampleToElement[(2*sdi)+1];
705 map<int, int>::const_iterator it = elemLocalIndicesInverse[p].find(
708 MFEM_VERIFY(it != elemLocalIndicesInverse[p].end(),
"");
709 MFEM_VERIFY(it->first == procElementIndex,
"");
711 const int sampleMeshElement = it->second;
713 spfespace[s]->GetElementVDofs(sampleMeshElement, eldofs);
714 const int eldof = eldofs[procElementDofIndex] >= 0 ?
715 eldofs[procElementDofIndex] : -1 - eldofs[procElementDofIndex];
716 s2sp[sdi] = eldof + spaceOS[s];
719 os[s] += local_num_sample_dofs_sub[s][p];
722 soffset += local_num_sample_dofs[p];
725 #ifdef FULL_DOF_STENCIL
728 for (
int i=0; i<s2sp.size(); ++i)
730 MFEM_VERIFY(s2sp[i] >= 0,
"");
735 #ifdef FULL_DOF_STENCIL
736 void Finish_s2sp_augmented(
const int rank,
const int nprocs,
737 vector<ParFiniteElementSpace*> & fespace,
738 vector<vector<int>>& dofs_block, vector<vector<int> >& dofs_sub_to_sdofs,
739 vector<vector<int> >& local_num_dofs_sub,
const bool dofsTrue,
742 const int nspaces = fespace.size();
746 int n = rank == 0 ? s2sp_.size() : 0;
747 MPI_Bcast(&n, 1, MPI_INT, 0, MPI_COMM_WORLD);
752 MPI_Bcast(s2sp.data(), n, MPI_INT, 0, MPI_COMM_WORLD);
755 for (
int s=0; s<nspaces; ++s)
758 for (
int p=0; p<rank; ++p)
759 os += local_num_dofs_sub[s][p];
763 for (
int p=0; p<nprocs; ++p)
764 sum += local_num_dofs_sub[s][p];
765 MFEM_VERIFY(dofs_sub_to_sdofs[s].size() == sum
766 && dofs_block[s].size() == sum,
"");
769 const int ndof = local_num_dofs_sub[s][rank];
770 MFEM_VERIFY(os + ndof <= dofs_block[s].size(),
"");
772 vector<int> gid(2*ndof);
778 map<int, int> tdofIndex;
779 for (
int i=0; i<ndof; ++i)
781 tdofIndex[dofs_block[s][os + i]] = i;
784 fdofs.assign(ndof, -1);
785 for (
int i=0; i<fespace[s]->GetVSize(); ++i)
787 const int ltdof = fespace[s]->GetLocalTDofNumber(i);
788 map<int, int>::const_iterator it = tdofIndex.find(ltdof);
789 if (it != tdofIndex.end())
791 MFEM_VERIFY(it->first == ltdof && fdofs[it->second] == -1,
"");
792 fdofs[it->second] = i;
796 bool fdofsSet =
true;
797 for (
int i=0; i<ndof; ++i)
803 MFEM_VERIFY(fdofsSet,
"");
804 for (
int i=0; i<ndof; ++i)
806 gid[2*i] = fespace[s]->GetGlobalTDofNumber(fdofs[i]);
811 for (
int i=0; i<ndof; ++i)
813 gid[2*i] = fespace[s]->GetGlobalTDofNumber(dofs_block[s][os + i]);
817 for (
int i=0; i<ndof; ++i)
819 gid[(2*i) + 1] = s2sp[dofs_sub_to_sdofs[s][os + i]];
822 vector<int> counts(nprocs);
823 vector<int> offsets(nprocs);
826 for (
int i=0; i<nprocs; ++i)
828 counts[i] = 2 * local_num_dofs_sub[s][i];
830 offsets[i] = offsets[i-1] + counts[i-1];
833 vector<int> allgid(offsets[nprocs-1] + counts[nprocs-1]);
835 MPI_Gatherv(gid.data(), 2*ndof, MPI_INT, allgid.data(), counts.data(),
836 offsets.data(), MPI_INT, 0, MPI_COMM_WORLD);
842 for (
int p=0; p<nprocs; ++p)
844 for (
int i=0; i<local_num_dofs_sub[s][p]; ++i)
846 const int g = allgid[offsets[p] + (2*i)];
847 const int sp = allgid[offsets[p] + (2*i) + 1];
849 map<int, int>::const_iterator it = gi2sp.find(g);
850 if (it == gi2sp.end())
854 MFEM_VERIFY(it->first == g,
"");
855 if (it->second == -1)
859 MFEM_VERIFY(it->second == sp,
"");
866 for (
int p=0; p<nprocs; ++p)
868 for (
int i=0; i<local_num_dofs_sub[s][p]; ++i)
870 const int g = allgid[offsets[p] + (2*i)];
872 map<int, int>::const_iterator it = gi2sp.find(g);
873 MFEM_VERIFY(it != gi2sp.end() && it->first == g,
"");
875 if (s2sp[dofs_sub_to_sdofs[s][os + i]] != -1)
877 MFEM_VERIFY(s2sp[dofs_sub_to_sdofs[s][os + i]] == it->second,
"");
880 s2sp[dofs_sub_to_sdofs[s][os + i]] = it->second;
883 os += local_num_dofs_sub[s][p];
886 for (
int i=0; i<s2sp_.size(); ++i)
891 MFEM_VERIFY(s2sp_[i] == s2sp[i],
"Consistency check");
896 for (
int i=0; i<s2sp_.size(); ++i)
897 MFEM_VERIFY(s2sp_[i] >= 0 && s2sp_[i] == s2sp[i],
"");
901 void ParaViewPrintAttributes(
const string &fname,
904 const Array<int> *el_number=
nullptr,
905 const Array<int> *vert_number=
nullptr)
907 ofstream out(fname +
".vtu");
909 out <<
"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\"";
910 out <<
" byte_order=\"" << VTKByteOrder() <<
"\">\n";
911 out <<
"<UnstructuredGrid>\n";
913 const string fmt_str =
"ascii";
915 int dim = mesh.Dimension();
923 ne = mesh.GetNEdges();
926 else if (entity_dim == 2)
932 ne = mesh.GetNFaces();
935 else if (entity_dim == 3)
939 int np = mesh.GetNV();
941 auto get_geom = [mesh,entity_dim,dim](
int i)
943 if (entity_dim == 1) {
944 return Geometry::SEGMENT;
946 else if (entity_dim == 2 && dim > 2) {
947 return mesh.GetFaceGeometry(i);
950 return mesh.GetElementGeometry(i);
954 auto get_verts = [mesh,entity_dim,dim](
int i, Array<int> &v)
956 if (entity_dim == dim) {
957 mesh.GetElementVertices(i, v);
959 else if (entity_dim == 1) {
960 mesh.GetEdgeVertices(i, v);
962 else if (entity_dim == 2) {
963 mesh.GetFaceVertices(i, v);
967 out <<
"<Piece NumberOfPoints=\"" << np <<
"\" NumberOfCells=\""
972 out <<
"<DataArray type=\"" <<
"Float64"
973 <<
"\" NumberOfComponents=\"3\" format=\"" << fmt_str <<
"\">\n";
974 for (
int i = 0; i < np; i++)
976 const double *v = mesh.GetVertex(i);
977 for (
int d = 0; d < 3; ++ d)
979 if (d < mesh.SpaceDimension()) {
988 out <<
"</DataArray>" << endl;
989 out <<
"</Points>" << endl;
991 out <<
"<Cells>" << endl;
992 out <<
"<DataArray type=\"Int32\" Name=\"connectivity\" format=\""
993 << fmt_str <<
"\">" << endl;
994 for (
int i = 0; i < ne; i++)
997 Geometry::Type geom = get_geom(i);
999 const int *p = VTKGeometry::VertexPermutation[geom];
1000 for (
int j = 0; j < v.Size(); ++j)
1002 out << v[p ? p[j] : j] <<
" ";
1006 out <<
"</DataArray>" << endl;
1008 out <<
"<DataArray type=\"Int32\" Name=\"offsets\" format=\""
1009 << fmt_str <<
"\">" << endl;
1012 for (
int i = 0; i < ne; ++i)
1017 out << coff <<
'\n';
1019 out <<
"</DataArray>" << endl;
1020 out <<
"<DataArray type=\"UInt8\" Name=\"types\" format=\""
1021 << fmt_str <<
"\">" << endl;
1023 for (
int i = 0; i < ne; i++)
1025 Geometry::Type geom = get_geom(i);
1026 out << VTKGeometry::Map[geom] <<
'\n';
1028 out <<
"</DataArray>" << endl;
1029 out <<
"</Cells>" << endl;
1031 out <<
"<CellData Scalars=\"attribute\">" << endl;
1036 if (entity_dim == dim) {
1037 array_name =
"element number";
1039 else if (entity_dim == 2) {
1040 array_name =
"face number";
1042 else if (entity_dim == 1) {
1043 array_name =
"edge number";
1045 out <<
"<DataArray type=\"Int32\" Name=\""
1046 << array_name <<
"\" format=\""
1047 << fmt_str <<
"\">" << endl;
1048 for (
int i = 0; i < ne; i++)
1050 out << (*el_number)[i] <<
'\n';
1052 out <<
"</DataArray>" << endl;
1054 out <<
"</CellData>" << endl;
1058 out <<
"<PointData>" << endl;
1059 out <<
"<DataArray type=\"Int32\" Name=\"vertex number\" format=\""
1060 << fmt_str <<
"\">" << endl;
1061 for (
int i = 0; i < np; i++)
1063 out << (*vert_number)[i] <<
'\n';
1065 out <<
"</DataArray>" << endl;
1066 out <<
"</PointData>" << endl;
1069 out <<
"</Piece>\n";
1070 out <<
"</UnstructuredGrid>\n";
1071 out <<
"</VTKFile>" << endl;
1075 string visFileName,
double visScale) :
1076 nspaces(fespace_.size()), fespace(fespace_), filename(visFileName),
1077 elemVisScale(visScale)
1079 MFEM_VERIFY(nspaces > 0,
"Must provide at least one finite element space");
1080 spfespace.assign(nspaces,
nullptr);
1082 pmesh = fespace[0]->GetParMesh();
1084 for (
int i=1; i<nspaces; ++i)
1086 MFEM_VERIFY(pmesh == fespace[i]->GetParMesh(),
1087 "All spaces must use the same full-order mesh");
1090 MPI_Comm_rank(MPI_COMM_WORLD, &myid);
1091 MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
1093 int color = (myid != 0);
1094 const int status = MPI_Comm_split(MPI_COMM_WORLD, color, myid, &root_comm);
1095 MFEM_VERIFY(status == MPI_SUCCESS,
1096 "Construction of hyperreduction comm failed");
1098 sample_dofs_proc.assign(nspaces, vector<set<int>> (nprocs));
1104 const int space, vector<int>
const& sample_dofs_v,
1105 vector<int>
const& num_sample_dofs_per_proc)
1107 MFEM_VERIFY(!finalized,
1108 "Cannot register a variable in a finalized SampleMeshManager");
1109 MFEM_VERIFY(0 <= space && space < nspaces,
"Invalid space index");
1110 MFEM_VERIFY(num_sample_dofs_per_proc.size() == nprocs,
"");
1113 auto search = vmap.find(variable);
1114 MFEM_VERIFY(search == vmap.end(),
1115 "Variable " + variable +
" is already registered!");
1117 vmap[variable] = nvar;
1119 for (
int p=0; p<nprocs; ++p)
1122 for (
int q=0; q<p; ++q)
1124 os += num_sample_dofs_per_proc[q];
1129 MFEM_VERIFY(os + num_sample_dofs_per_proc[p] == sample_dofs_v.size(),
"");
1132 for (
int j=0; j<num_sample_dofs_per_proc[p]; ++j)
1133 sample_dofs_proc[space][p].insert(sample_dofs_v[os + j]);
1136 num_sample_dofs_per_proc_var.push_back(num_sample_dofs_per_proc);
1137 sample_dofs_var.push_back(sample_dofs_v);
1138 varSpace.push_back(space);
1139 nvar = varSpace.size();
1142 void SampleMeshManager::SetSampleMaps()
1144 num_sample_dofs_per_proc_merged.assign(nprocs, 0);
1146 vector<vector<int>> allspaceTOS(nspaces);
1148 for (
int i=0; i<nspaces; ++i)
1150 allspaceTOS[i].resize(nprocs);
1151 MPI_Allgather(&spaceTOS[i], 1, MPI_INT, allspaceTOS[i].data(), 1, MPI_INT,
1155 for (
int p=0; p<nprocs; ++p)
1157 vector<int> sample_dofs_os(nspaces);
1159 for (
int i=0; i<nspaces; ++i)
1161 num_sample_dofs_per_proc_merged[p] += sample_dofs_proc[i][p].size();
1162 const int os = allspaceTOS[i][p];
1163 sample_dofs_os[i] = sample_dofs.size();
1165 for (set<int>::const_iterator it = sample_dofs_proc[i][p].begin();
1166 it != sample_dofs_proc[i][p].end(); ++it)
1168 sample_dofs.push_back(os + (*it));
1174 s2sp_var.resize(nvar);
1175 for (
int v=0; v<nvar; ++v)
1177 const int space = varSpace[v];
1180 for (
int q=0; q<p; ++q)
1181 os += num_sample_dofs_per_proc_var[v][q];
1183 const int nvs = sample_dofs_var[v].size();
1184 s2sp_var[v].resize(nvs);
1186 for (
int j=0; j<num_sample_dofs_per_proc_var[v][p]; ++j)
1188 const int sample = sample_dofs_var[v][os + j];
1194 for (set<int>::const_iterator it = sample_dofs_proc[space][p].begin();
1195 it != sample_dofs_proc[space][p].end(); ++it, ++cnt)
1199 MFEM_VERIFY(k == -1,
"");
1204 MFEM_VERIFY(k >= 0,
"");
1205 s2sp_var[v][os + j] = sample_dofs_os[space] + k;
1213 MFEM_VERIFY(!finalized,
"Sample mesh is already constructed");
1215 nvar = varSpace.size();
1216 MFEM_VERIFY(nvar == sample_dofs_var.size()
1217 && nvar == num_sample_dofs_per_proc_var.size(),
"");
1219 spaceOS.assign(nspaces + 1, 0);
1220 spaceTOS.assign(nspaces + 1, 0);
1221 spaceOSSP.assign(nspaces, 0);
1223 for (
int i=0; i<nspaces; ++i)
1225 spaceOS[i+1] = spaceOS[i] + fespace[i]->GetVSize();
1226 spaceTOS[i+1] = spaceTOS[i] + fespace[i]->GetTrueVSize();
1234 for (
int i = 0; i < nspaces - 1; ++i)
1236 spaceOSSP[i+1] = spaceOSSP[i] + spfespace[i]->GetVSize();
1239 sample_pmesh->EnsureNodes();
1247 void SampleMeshManager::FinishSampleMaps()
1252 vector<int> data(nprocs * (nspaces+1));
1253 MPI_Allgather(spaceTOS.data(), nspaces+1, MPI_INT, data.data(), nspaces+1,
1254 MPI_INT, MPI_COMM_WORLD);
1256 spaceOSall.assign(nspaces+1, vector<int> (nprocs, 0));
1257 for (
int p=0; p<nprocs; ++p)
1258 for (
int s=0; s<nspaces+1; ++s)
1259 spaceOSall[s][p] = data[(p*(nspaces+1)) + s];
1266 for (
int p=0; p<nprocs; ++p)
1268 for (
int i=0; i<num_sample_dofs_per_proc_merged[p]; ++i)
1271 int s = nspaces - 1;
1272 while (sample_dofs[offset + i] < spaceOSall[s][p])
1276 offset += num_sample_dofs_per_proc_merged[p];
1279 MFEM_VERIFY(s2sp.size() == offset,
"");
1282 for (
int v=0; v<nvar; ++v)
1284 const int s = varSpace[v];
1286 for (
int p=0; p<nprocs; ++p)
1288 for (
int j=0; j<num_sample_dofs_per_proc_var[v][p]; ++j)
1290 MFEM_VERIFY(spaceOSall[s][p] <= sample_dofs[s2sp_var[v][os_p + j]]
1291 && sample_dofs[s2sp_var[v][os_p + j]] < spaceOSall[s+1][p],
"");
1292 const int spId = s2sp[s2sp_var[v][os_p + j]];
1293 s2sp_var[v][os_p + j] = spId - spaceOSSP[s];
1296 os_p += num_sample_dofs_per_proc_var[v][p];
1299 MFEM_VERIFY(os_p == sample_dofs_var[v].size(),
"");
1305 const int var = GetVariableIndex(variable);
1306 return sample_dofs_var[var].size();
1312 const int var = GetVariableIndex(variable);
1313 const int n = s2sp_var[var].size();
1314 const int space = varSpace[var];
1315 MFEM_VERIFY(s.
dim() == n,
"");
1316 MFEM_VERIFY(v.Size() == spfespace[space]->GetTrueVSize(),
"");
1317 for (
int i=0; i<n; ++i)
1318 s(i) = v[s2sp_var[var][i]];
1322 string file_name)
const
1324 const int var = GetVariableIndex(variable);
1326 file.open(file_name);
1327 for (
int i=0; i<s2sp_var[var].size(); ++i)
1329 file << s2sp_var[var][i] << endl;
1334 void GatherDistributedMatrixRows_aux(
const CAROM::Matrix& B,
const int rdim,
1335 #ifdef FULL_DOF_STENCIL
1336 const int os0,
const int os1,
const int ossp,
1337 ParFiniteElementSpace& fespace,
1339 const vector<int>& st2sp,
const vector<int>& sprows,
1345 int num_procs, myid;
1346 MPI_Comm_size(MPI_COMM_WORLD, &num_procs);
1347 MPI_Comm_rank(MPI_COMM_WORLD, &myid);
1350 vector<int> allos0(num_procs);
1351 vector<int> allos1(num_procs);
1353 MPI_Allgather(&os0, 1, MPI_INT, allos0.data(), 1, MPI_INT, MPI_COMM_WORLD);
1354 MPI_Allgather(&os1, 1, MPI_INT, allos1.data(), 1, MPI_INT, MPI_COMM_WORLD);
1356 const int num_sprows =
static_cast<int>(sprows.size());
1358 #ifdef FULL_DOF_STENCIL
1359 int num_sprows_true = 0;
1360 for (
auto i : sprows)
1362 if (i >= os0 && i < os1 && fespace.GetLocalTDofNumber(i - os0) >= 0)
1368 vector<int> sprows_true(num_sprows_true);
1371 for (
int j=0; j<sprows.size(); ++j)
1373 const int i = sprows[j];
1374 if (i >= os0 && i < os1 && fespace.GetLocalTDofNumber(i - os0) >= 0)
1376 sprows_true[tcnt] = j;
1381 MFEM_VERIFY(tcnt == num_sprows_true,
"");
1385 int* cts =
new int [num_procs];
1386 #ifdef FULL_DOF_STENCIL
1387 MPI_Allgather(&num_sprows_true, 1, MPI_INT, cts, 1, MPI_INT, MPI_COMM_WORLD);
1388 int* allNSP =
new int [num_procs];
1389 MPI_Allgather(&num_sprows, 1, MPI_INT, allNSP, 1, MPI_INT, MPI_COMM_WORLD);
1390 int* offsetSP =
new int [num_procs];
1392 for (
int i = 1; i < num_procs; ++i) {
1393 offsetSP[i] = offsetSP[i-1] + allNSP[i-1];
1396 MPI_Allgather(&num_sprows, 1, MPI_INT, cts, 1, MPI_INT, MPI_COMM_WORLD);
1398 int* offsets =
new int [num_procs];
1400 for (
int i = 1; i < num_procs; ++i) {
1401 offsets[i] = offsets[i-1] + cts[i-1];
1404 #ifdef FULL_DOF_STENCIL
1405 const int total_num_sprows_true = offsets[num_procs-1] + cts[num_procs-1];
1406 vector<int> all_sprows_true(total_num_sprows_true);
1408 MPI_Allgatherv(sprows_true.data(), num_sprows_true,
1409 MPI_INT, all_sprows_true.data(), cts,
1410 offsets, MPI_INT, MPI_COMM_WORLD);
1412 MFEM_VERIFY(offsets[num_procs-1] + cts[num_procs-1] == all_sprows.size(),
"");
1416 const int Nsp = Bsp.
numRows();
1418 for (
int i = 0; i < num_sprows; i++) {
1419 int row = sprows[i];
1420 if (os0 <= row && row < os1)
1422 #ifdef FULL_DOF_STENCIL
1423 const int ltdof = fespace.GetLocalTDofNumber(row - os0);
1424 if (ltdof >= 0 && st2sp[i] >= 0)
1426 MFEM_VERIFY(0 <= st2sp[i] - ossp && st2sp[i] - ossp < Nsp,
"");
1428 for (
int j = 0; j < rdim; ++j)
1429 Bsp(st2sp[i] - ossp, j) = B(ltdof, j);
1432 for (
int j = 0; j < rdim; ++j)
1433 Bsp(st2sp[i], j) = B(row, j);
1438 #ifdef FULL_DOF_STENCIL
1439 int Bsp_row = num_sprows_true;
1441 int Bsp_row = num_sprows;
1444 for (
int i = 1; i < num_procs; ++i) {
1445 for (
int j = 0; j < cts[i]; ++j) {
1446 #ifdef FULL_DOF_STENCIL
1447 const int sti = offsetSP[i] + all_sprows_true[Bsp_row];
1448 if (allos0[i] <= all_sprows[sti] && all_sprows[sti] < allos1[i])
1450 MFEM_VERIFY(0 <= st2sp[sti] - ossp && st2sp[sti] - ossp < Bsp.
numRows(),
"");
1452 MPI_Recv(&Bsp(st2sp[sti] - ossp, 0), rdim, MPI_DOUBLE,
1453 i, offsets[i]+j, MPI_COMM_WORLD, &status);
1456 if (allos0[i] <= all_sprows[Bsp_row] && all_sprows[Bsp_row] < allos1[i])
1459 MPI_Recv(&Bsp(st2sp[Bsp_row], 0), rdim, MPI_DOUBLE,
1460 i, offsets[i]+j, MPI_COMM_WORLD, &status);
1467 #ifdef FULL_DOF_STENCIL
1468 MFEM_VERIFY(Bsp_row == all_sprows_true.size(),
"");
1470 MFEM_VERIFY(Bsp_row == all_sprows.size(),
"");
1474 double* v =
new double [rdim];
1475 #ifdef FULL_DOF_STENCIL
1476 for (
int i = 0; i < num_sprows_true; i++) {
1478 if (os0 <= sprows[sprows_true[i]] && sprows[sprows_true[i]] < os1)
1479 row = fespace.GetLocalTDofNumber(sprows[sprows_true[i]] - os0);
1481 MFEM_VERIFY(row >= 0,
"");
1483 if (os0 <= sprows[sprows_true[i]] && sprows[sprows_true[i]] < os1)
1485 for (
int i = 0; i < num_sprows; i++) {
1486 int row = sprows[i];
1487 if (os0 <= row && row < os1)
1490 for (
int j = 0; j < rdim; ++j)
1492 MPI_Send(v, rdim, MPI_DOUBLE, 0, offsets[myid]+i, MPI_COMM_WORLD);
1499 #ifdef FULL_DOF_STENCIL
1505 int SampleMeshManager::GetVariableIndex(
const string variable)
const
1507 auto search = vmap.find(variable);
1508 MFEM_VERIFY(search != vmap.end(),
1509 "Variable " + variable +
" is not registered!");
1510 const int var = search->second;
1511 MFEM_VERIFY(0 <= var && var < nvar,
"Invalid variable index");
1518 const int var = GetVariableIndex(variable);
1519 const int s = varSpace[var];
1521 GatherDistributedMatrixRows_aux(B, rdim, spaceOS[s], spaceOS[s+1], spaceOSSP[s],
1522 *fespace[s], st2sp, sprows, all_sprows, Bsp);
1525 void SampleMeshManager::CreateSampleMesh()
1527 MFEM_VERIFY(nspaces > 0,
"");
1529 vector<vector<int> > sample_dofs_block(nspaces);
1530 vector<vector<int> > sample_dofs_sub_to_sample_dofs(nspaces);
1531 vector<vector<int> > local_num_sample_dofs_sub(nspaces);
1532 vector<vector<int> > localSampleDofsToElem_sub(nspaces);
1533 vector<vector<int> > localSampleDofsToElemDof_sub(nspaces);
1535 vector<int> Ntrue(nspaces);
1536 for (
int i=0; i<nspaces; ++i)
1537 Ntrue[i] = fespace[i]->TrueVSize();
1539 vector<int>& local_num_sample_dofs = num_sample_dofs_per_proc_merged;
1541 SplitDofsIntoBlocks(Ntrue, sample_dofs, local_num_sample_dofs,
1542 sample_dofs_block, sample_dofs_sub_to_sample_dofs, local_num_sample_dofs_sub);
1544 const bool getSampledEntities = !filename.empty();
1546 set<int> intElems, faces, edges, vertices;
1549 GetLocalSampleMeshElements(*pmesh, *fespace[0], sample_dofs_block[0],
1550 local_num_sample_dofs_sub[0], elems,
1551 getSampledEntities, intElems, faces, edges, vertices);
1552 GetLocalDofsToLocalElementMap(*fespace[0], sample_dofs_block[0],
1553 local_num_sample_dofs_sub[0], elems, localSampleDofsToElem_sub[0],
1554 localSampleDofsToElemDof_sub[0],
true);
1555 for (
int i=1; i<nspaces; ++i)
1558 set<int> intElems_i, faces_i, edges_i,
1561 GetLocalSampleMeshElements(*pmesh, *fespace[i], sample_dofs_block[i],
1562 local_num_sample_dofs_sub[i], elems_i,
1563 getSampledEntities, intElems_i, faces_i, edges_i, vertices_i);
1564 GetLocalDofsToLocalElementMap(*fespace[i], sample_dofs_block[i],
1565 local_num_sample_dofs_sub[i], elems_i, localSampleDofsToElem_sub[i],
1566 localSampleDofsToElemDof_sub[i],
true);
1569 elems.insert(elems_i.begin(), elems_i.end());
1571 if (getSampledEntities)
1573 intElems.insert(intElems_i.begin(), intElems_i.end());
1574 faces.insert(faces_i.begin(), faces_i.end());
1575 edges.insert(edges_i.begin(), edges_i.end());
1576 vertices.insert(vertices_i.begin(), vertices_i.end());
1580 vector<int> elemLocalIndices;
1581 vector<map<int, int> > elemLocalIndicesInverse;
1582 Mesh *sample_mesh = 0;
1583 BuildSampleMesh(*pmesh, fespace, elems, sample_mesh, sprows, elemLocalIndices,
1584 elemLocalIndicesInverse);
1586 MFEM_VERIFY(sample_mesh->GetNE() == elemLocalIndices.size(),
"");
1590 sample_pmesh =
new ParMesh(root_comm, *sample_mesh);
1594 for (
int i=0; i<nspaces; ++i)
1595 spfespace[i] =
new ParFiniteElementSpace(sample_pmesh, fespace[i]->FEColl(),
1596 fespace[i]->GetVDim());
1599 vector<int> spNtrue(nspaces);
1600 for (
int i=0; i<nspaces; ++i)
1601 spNtrue[i] = myid == 0 ? spfespace[i]->TrueVSize() : 0;
1603 Set_s2sp(myid, nprocs, spNtrue, sample_dofs.size(), local_num_sample_dofs,
1604 local_num_sample_dofs_sub, localSampleDofsToElem_sub,
1605 localSampleDofsToElemDof_sub, sample_dofs_sub_to_sample_dofs,
1606 elemLocalIndicesInverse, spfespace, s2sp);
1608 #ifdef FULL_DOF_STENCIL
1609 Finish_s2sp_augmented(myid, nprocs, fespace, sample_dofs_block,
1610 sample_dofs_sub_to_sample_dofs, local_num_sample_dofs_sub,
true, s2sp);
1615 const int numStencil = sprows.size();
1616 vector<int> local_num_stencil_dofs(nprocs);
1618 MPI_Allgather(&numStencil, 1, MPI_INT, &local_num_stencil_dofs[0], 1, MPI_INT,
1621 int* offsets =
new int [nprocs];
1623 for (
int i = 1; i < nprocs; ++i)
1624 offsets[i] = offsets[i-1] + local_num_stencil_dofs[i-1];
1626 const int total_num_stencil_dofs = offsets[nprocs-1] +
1627 local_num_stencil_dofs[nprocs-1];
1629 all_sprows.resize(total_num_stencil_dofs);
1630 MPI_Allgatherv(&sprows[0], local_num_stencil_dofs[myid],
1631 MPI_INT, &all_sprows[0], &local_num_stencil_dofs[0],
1632 offsets, MPI_INT, MPI_COMM_WORLD);
1639 vector<vector<int>> stencil_dofs_block(nspaces);
1640 vector<vector<int> > stencil_dofs_sub_to_stencil_dofs(nspaces);
1641 vector<vector<int> > local_num_stencil_dofs_sub(nspaces);
1642 vector<vector<int> > localStencilDofsToElem_sub(nspaces);
1643 vector<vector<int> > localStencilDofsToElemDof_sub(nspaces);
1645 #ifdef FULL_DOF_STENCIL
1646 vector<int> Nfull(nspaces);
1647 for (
int i=0; i<nspaces; ++i)
1648 Nfull[i] = fespace[i]->GetVSize();
1650 SplitDofsIntoBlocks(Nfull, all_sprows, local_num_stencil_dofs,
1651 stencil_dofs_block, stencil_dofs_sub_to_stencil_dofs,
1652 local_num_stencil_dofs_sub);
1654 SplitDofsIntoBlocks(Ntrue, all_sprows, local_num_stencil_dofs,
1655 stencil_dofs_block, stencil_dofs_sub_to_stencil_dofs,
1656 local_num_stencil_dofs_sub);
1659 for (
int i=0; i<nspaces; ++i)
1661 GetLocalDofsToLocalElementMap(*fespace[i], stencil_dofs_block[i],
1662 local_num_stencil_dofs_sub[i], elems, localStencilDofsToElem_sub[i],
1663 localStencilDofsToElemDof_sub[i],
false);
1666 Set_s2sp(myid, nprocs, spNtrue, all_sprows.size(), local_num_stencil_dofs,
1667 local_num_stencil_dofs_sub, localStencilDofsToElem_sub,
1668 localStencilDofsToElemDof_sub, stencil_dofs_sub_to_stencil_dofs,
1669 elemLocalIndicesInverse, spfespace, st2sp);
1671 #ifdef FULL_DOF_STENCIL
1672 Finish_s2sp_augmented(myid, nprocs, fespace, stencil_dofs_block,
1673 stencil_dofs_sub_to_stencil_dofs, local_num_stencil_dofs_sub,
false, st2sp);
1676 if (!filename.empty())
1678 SampleVisualization(pmesh, elems, intElems, faces, edges, vertices,
1679 filename,
nullptr, elemVisScale);
1683 void SampleVisualization(ParMesh *pmesh, set<int>
const& elems,
1684 set<int>
const& intElems, set<int>
const& faces,
1685 set<int>
const& edges, set<int>
const& vertices,
1686 string const& filename, mfem::Vector *elemCount,
1687 double elementScaling)
1696 L2_FECollection l2_coll(1, pmesh->Dimension());
1697 ParFiniteElementSpace pwc_space(pmesh, &l2_coll);
1699 ParGridFunction marker(&pwc_space);
1703 MFEM_VERIFY(elemCount->Size() == pmesh->GetNE(),
"");
1704 for (
int e=0; e<pmesh->GetNE(); ++e)
1707 pwc_space.GetElementVDofs(e, dofs);
1709 for (
int i = 0; i < dofs.Size(); i++)
1711 const int dof_i = dofs[i] >= 0 ? dofs[i] : -1 - dofs[i];
1712 marker[dof_i] = (*elemCount)[e];
1718 for (set<int>::const_iterator it = elems.begin(); it != elems.end(); ++it)
1721 pwc_space.GetElementVDofs(*it, dofs);
1723 for (
int i = 0; i < dofs.Size(); i++)
1725 const int dof_i = dofs[i] >= 0 ? dofs[i] : -1 - dofs[i];
1726 marker[dof_i] = elementScaling;
1731 VisItDataCollection visit_dc(filename, pmesh);
1732 visit_dc.RegisterField(
"Sample Elements", &marker);
1733 visit_dc.SetFormat(DataCollection::SERIAL_FORMAT);
1737 int ne = pmesh->GetNE();
1738 int nv = pmesh->GetNV();
1739 int nf = pmesh->GetNFaces();
1740 int nedge = pmesh->GetNEdges();
1742 Array<int> e(ne), v(nv), f(nf), edge(nedge);
1748 for (set<int>::const_iterator it = intElems.begin(); it != intElems.end(); ++it)
1753 for (set<int>::const_iterator it = faces.begin(); it != faces.end(); ++it)
1758 for (set<int>::const_iterator it = edges.begin(); it != edges.end(); ++it)
1763 for (set<int>::const_iterator it = vertices.begin(); it != vertices.end(); ++it)
1775 ParaViewPrintAttributes(filename +
"_pv", *pmesh, pmesh->Dimension(), &e, &v);
1776 if (pmesh->Dimension() == 3)
1778 ParaViewPrintAttributes(filename +
"_pv_face", *pmesh, 2, &f, &v);
1780 ParaViewPrintAttributes(filename +
"_pv_edge", *pmesh, 1, &edge, &v);
1786 auto search = vmap.find(variable);
1787 MFEM_VERIFY(search == vmap.end(),
1788 "Map for variable " + variable +
" is already read!");
1790 vmap[variable] = nvar;
1794 file.open(file_name);
1796 while(getline(file, line)) {
1797 v.push_back(stoi(line));
1801 s2sp_var.push_back(v);
1802 nvar = s2sp_var.size();
1805 int SampleDOFSelector::GetVariableIndex(
const string variable)
const
1807 auto search = vmap.find(variable);
1808 MFEM_VERIFY(search != vmap.end(),
1809 "Variable " + variable +
" is not registered!");
1810 const int var = search->second;
1811 MFEM_VERIFY(0 <= var && var < nvar,
"Invalid variable index");
1818 const int var = GetVariableIndex(variable);
1820 const int n = s2sp_var[var].size();
1821 MFEM_VERIFY(s.
dim() == n,
"");
1822 for (
int i=0; i<n; ++i)
1823 s(i) = v[s2sp_var[var][i]];
int numColumns() const
Returns the number of columns in the Matrix. This method will return the same value from each process...
int numRows() const
Returns the number of rows of the Matrix on this processor.
void ReadMapFromFile(const string variable, string file_name)
Reads a variable sample DOF map from file, written by SampleMeshManager::WriteVariableSampleMap,...
void GetSampledValues(const string variable, mfem::Vector const &v, CAROM::Vector &s) const
Sets a vector of sampled DOFs from a vector on the sample mesh space. Note that this function is the ...
void GetSampledValues(const string variable, mfem::Vector const &v, CAROM::Vector &s) const
Sets a vector of sampled DOFs from a vector on the sample mesh space.
void RegisterSampledVariable(const string variable, const int space, vector< int > const &sample_dofs_v, vector< int > const &num_sample_dofs_per_proc)
Register a variable and set its sampled DOFs.
void ConstructSampleMesh()
Construct the sample mesh, after registering all sampled variables.
SampleMeshManager(vector< ParFiniteElementSpace * > &fespace_, string visFileName="", double visScale=1.0)
Constructor creating a SampleMeshManager with arbitrarily many ParFiniteElementSpaces on a full-order...
int GetNumVarSamples(const string variable) const
Returns the number of sampled DOFs on all processes for a variable.
void WriteVariableSampleMap(const string variable, string file_name) const
Writes a variable sample DOF map to file, which can be read by SampleDOFSelector::ReadMapFromFile in ...
void GatherDistributedMatrixRows(const string variable, CAROM::Matrix const &B, const int rdim, CAROM::Matrix &Bsp) const
Gather the rows of a distributed basis CAROM::Matrix corresponding to a sample mesh space.
int dim() const
Returns the dimension of the Vector on this processor.