PETSC_STATIC_INLINE PetscErrorCode DMPlexGetGlobalFieldOffset_Private(DM dm,PetscInt point,PetscInt field,PetscInt *offset) { PetscFunctionBegin; #if defined(PETSC_USE_DEBUG) { PetscErrorCode ierr; PetscInt loff,lfoff,dof,cdof; ierr = PetscSectionGetOffset(dm->defaultGlobalSection,point,offset);CHKERRQ(ierr); ierr = PetscSectionGetOffset(dm->defaultSection,point,&loff);CHKERRQ(ierr); ierr = PetscSectionGetFieldOffset(dm->defaultSection,point,field,&lfoff);CHKERRQ(ierr); ierr = PetscSectionGetFieldDof(dm->defaultSection,point,field,&dof);CHKERRQ(ierr); ierr = PetscSectionGetFieldConstraintDof(dm->defaultSection,point,field,&cdof);CHKERRQ(ierr); *offset += lfoff - loff; if (dof-cdof <= 0) *offset = -1; /* Indicates no data */ } #else { PetscSection s = dm->defaultSection; PetscSection fs = dm->defaultSection->field[field]; PetscSection gs = dm->defaultGlobalSection; PetscInt dof,cdof,loff,lfoff; loff = s->atlasOff[point - s->pStart]; lfoff = fs->atlasOff[point - s->pStart]; dof = s->atlasDof[point - s->pStart]; cdof = s->bc ? s->bc->atlasDof[point - s->bc->pStart] : 0; *offset = gs->atlasOff[point - s->pStart] + lfoff - loff; if (dof-cdof <= 0) *offset = -1; } #endif PetscFunctionReturn(0); }
PetscErrorCode CreatePressureNullSpace(DM dm, AppCtx *user, MatNullSpace *nullSpace) { Vec vec, localVec; PetscErrorCode ierr; PetscFunctionBeginUser; ierr = DMGetGlobalVector(dm, &vec);CHKERRQ(ierr); ierr = DMGetLocalVector(dm, &localVec);CHKERRQ(ierr); ierr = VecSet(vec, 0.0);CHKERRQ(ierr); /* Put a constant in for all pressures Could change this to project the constant function onto the pressure space (when that is finished) */ { PetscSection section; PetscInt pStart, pEnd, p; PetscScalar *a; ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); ierr = VecGetArray(localVec, &a);CHKERRQ(ierr); for (p = pStart; p < pEnd; ++p) { PetscInt fDim, off, d; ierr = PetscSectionGetFieldDof(section, p, 1, &fDim);CHKERRQ(ierr); ierr = PetscSectionGetFieldOffset(section, p, 1, &off);CHKERRQ(ierr); for (d = 0; d < fDim; ++d) a[off+d] = 1.0; } ierr = VecRestoreArray(localVec, &a);CHKERRQ(ierr); } ierr = DMLocalToGlobalBegin(dm, localVec, INSERT_VALUES, vec);CHKERRQ(ierr); ierr = DMLocalToGlobalEnd(dm, localVec, INSERT_VALUES, vec);CHKERRQ(ierr); ierr = DMRestoreLocalVector(dm, &localVec);CHKERRQ(ierr); ierr = VecNormalize(vec, NULL);CHKERRQ(ierr); if (user->debug) { ierr = PetscPrintf(PetscObjectComm((PetscObject)dm), "Pressure Null Space\n");CHKERRQ(ierr); ierr = VecView(vec, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); } ierr = MatNullSpaceCreate(PetscObjectComm((PetscObject)dm), PETSC_FALSE, 1, &vec, nullSpace);CHKERRQ(ierr); ierr = DMRestoreGlobalVector(dm, &vec);CHKERRQ(ierr); /* New style for field null spaces */ { PetscObject pressure; MatNullSpace nullSpacePres; ierr = DMGetField(dm, 1, &pressure);CHKERRQ(ierr); ierr = MatNullSpaceCreate(PetscObjectComm(pressure), PETSC_TRUE, 0, NULL, &nullSpacePres);CHKERRQ(ierr); ierr = PetscObjectCompose(pressure, "nullspace", (PetscObject) nullSpacePres);CHKERRQ(ierr); ierr = MatNullSpaceDestroy(&nullSpacePres);CHKERRQ(ierr); } PetscFunctionReturn(0); }
PETSC_STATIC_INLINE PetscErrorCode DMPlexGetLocalFieldOffset_Private(DM dm,PetscInt point,PetscInt field,PetscInt *offset) { PetscFunctionBegin; #if defined(PETSC_USE_DEBUG) { PetscErrorCode ierr; ierr = PetscSectionGetFieldOffset(dm->defaultSection,point,field,offset);CHKERRQ(ierr); } #else { PetscSection s = dm->defaultSection->field[field]; *offset = s->atlasOff[point - s->pStart]; } #endif PetscFunctionReturn(0); }
void test(DM mesh) { const int dim = 2; const int field_count = 1; int components[field_count]; int dof[field_count*(dim+1)]; // Field 0 - temperature components[0] = 1; dof[0*(dim+1) + 0] = 1; // vertices dof[0*(dim+1) + 1] = 0; // faces // Field 1 - pressure components[1] = 1; dof[1*(dim+1) + 0] = 64; // vertices dof[1*(dim+1) + 1] = 0; // faces PetscSection section; DMPlexCreateSection(mesh, dim, // Spatial dimension field_count, // Number of fields components, // Component count for each field dof, // DoF for each field component 0, // Number of boundary conditions NULL, // BC Field NULL, // BC Points §ion); DMSetDefaultSection(mesh, section); // Temperature // Create a global vector Vec temperature = NULL; DMCreateGlobalVector(mesh, &temperature); // Get a temporary local vector & a pointer to its data Vec localTemp = NULL; DMGetLocalVector(mesh, &localTemp); PetscScalar * data = NULL; VecGetArray(localTemp, &data); // Loop over points in the section int start, end; DMGetDefaultSection(mesh, §ion); PetscSectionGetChart(section, &start, &end); for (int point=start; point<end; ++point) { // Get the size & offset of field 0 int dof, offset; PetscSectionGetFieldDof(section, point, 0, &dof); PetscSectionGetFieldOffset(section, point, 0, &offset); // Set values for (int d=0; d<dof; ++d){ data[offset+d] = point * 100 + d; } } VecRestoreArray(localTemp, &data); // Broadcast values DMLocalToGlobalBegin(mesh, localTemp, INSERT_VALUES, temperature); DMLocalToGlobalEnd(mesh, localTemp, INSERT_VALUES, temperature); // Now each node should have all temperature values // Free the temp vector DMRestoreLocalVector(mesh,&localTemp); }