petscdmlibmesh.C
Go to the documentation of this file.00001 #include "libmesh/petsc_macro.h" 00002 // This only works with petsc-3.3 and above. 00003 00004 #if !PETSC_VERSION_LESS_THAN(3,3,0) 00005 00006 // PETSc includes 00007 #include <petsc-private/dmimpl.h> 00008 00009 // Local Includes 00010 #include "libmesh/libmesh_common.h" 00011 #include "libmesh/nonlinear_implicit_system.h" 00012 #include "libmesh/petsc_dm_nonlinear_solver.h" 00013 #include "libmesh/petsc_linear_solver.h" 00014 #include "libmesh/petsc_vector.h" 00015 #include "libmesh/petsc_matrix.h" 00016 #include "libmesh/petscdmlibmesh.h" 00017 #include "libmesh/dof_map.h" 00018 #include "libmesh/preconditioner.h" 00019 00020 using namespace libMesh; 00021 00022 #define DMLIBMESH_NO_DECOMPOSITION 0 00023 #define DMLIBMESH_FIELD_DECOMPOSITION 1 00024 #define DMLIBMESH_DOMAIN_DECOMPOSITION 2 00025 00026 #define DMLIBMESH_NO_EMBEDDING 0 00027 #define DMLIBMESH_FIELD_EMBEDDING 1 00028 #define DMLIBMESH_DOMAIN_EMBEDDING 2 00029 00030 struct DM_libMesh 00031 { 00032 NonlinearImplicitSystem* sys; 00033 std::map<std::string, unsigned int> *varids; 00034 std::map<unsigned int, std::string> *varnames; 00035 std::map<std::string, unsigned int> *blockids; 00036 std::map<unsigned int, std::string> *blocknames; 00037 unsigned int decomposition_type; 00038 std::vector<std::set<unsigned int> > *decomposition; 00039 unsigned int embedding_type; 00040 IS embedding; 00041 }; 00042 00043 #undef __FUNCT__ 00044 #define __FUNCT__ "DMLibMeshGetBlocks" 00045 PetscErrorCode DMLibMeshGetBlocks(DM dm, PetscInt *n, char*** blocknames) 00046 { 00047 PetscErrorCode ierr; 00048 PetscInt i; 00049 PetscFunctionBegin; 00050 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 00051 PetscBool islibmesh; 00052 ierr = PetscObjectTypeCompare((PetscObject)dm, DMLIBMESH,&islibmesh); 00053 if(!islibmesh) SETERRQ2(((PetscObject)dm)->comm, PETSC_ERR_ARG_WRONG, "Got DM oftype %s, not of type %s", ((PetscObject)dm)->type_name, DMLIBMESH); 00054 DM_libMesh *dlm = (DM_libMesh *)(dm->data); 00055 PetscValidPointer(n,2); 00056 *n = dlm->blockids->size(); 00057 if(!blocknames) PetscFunctionReturn(0); 00058 ierr = PetscMalloc(*n*sizeof(char*), blocknames); CHKERRQ(ierr); 00059 i = 0; 00060 for(std::map<std::string, unsigned int>::const_iterator it = dlm->blockids->begin(); it != dlm->blockids->end(); ++it){ 00061 ierr = PetscStrallocpy(it->first.c_str(), *blocknames+i); CHKERRQ(ierr); 00062 ++i; 00063 } 00064 PetscFunctionReturn(0); 00065 } 00066 00067 #undef __FUNCT__ 00068 #define __FUNCT__ "DMLibMeshGetVariables" 00069 PetscErrorCode DMLibMeshGetVariables(DM dm, PetscInt *n, char*** varnames) 00070 { 00071 PetscErrorCode ierr; 00072 PetscFunctionBegin; 00073 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 00074 PetscBool islibmesh; 00075 PetscInt i; 00076 ierr = PetscObjectTypeCompare((PetscObject)dm, DMLIBMESH,&islibmesh); 00077 if(!islibmesh) SETERRQ2(((PetscObject)dm)->comm, PETSC_ERR_ARG_WRONG, "Got DM oftype %s, not of type %s", ((PetscObject)dm)->type_name, DMLIBMESH); 00078 DM_libMesh *dlm = (DM_libMesh *)(dm->data); 00079 PetscValidPointer(n,2); 00080 *n = dlm->varids->size(); 00081 if(!varnames) PetscFunctionReturn(0); 00082 ierr = PetscMalloc(*n*sizeof(char*), varnames); CHKERRQ(ierr); 00083 i = 0; 00084 for(std::map<std::string, unsigned int>::const_iterator it = dlm->varids->begin(); it != dlm->varids->end(); ++it){ 00085 ierr = PetscStrallocpy(it->first.c_str(), *varnames+i); CHKERRQ(ierr); 00086 ++i; 00087 } 00088 PetscFunctionReturn(0); 00089 } 00090 00091 #undef __FUNCT__ 00092 #define __FUNCT__ "DMLibMeshSetUpName_Private" 00093 PetscErrorCode DMLibMeshSetUpName_Private(DM dm) 00094 { 00095 DM_libMesh* dlm = (DM_libMesh*)dm->data; 00096 PetscErrorCode ierr; 00097 PetscFunctionBegin; 00098 std::string name = dlm->sys->name(); 00099 std::map<unsigned int, std::string> *dnames = PETSC_NULL, *enames = PETSC_NULL; 00100 if(dlm->decomposition_type == DMLIBMESH_FIELD_DECOMPOSITION) { 00101 name += ":dec:var:"; 00102 dnames = dlm->varnames; 00103 } 00104 if(dlm->decomposition_type == DMLIBMESH_DOMAIN_DECOMPOSITION) { 00105 name += ":dec:block:"; 00106 dnames = dlm->blocknames; 00107 } 00108 if(dnames) { 00109 for(unsigned int d = 0; d < dlm->decomposition->size(); ++d) { 00110 for(std::set<unsigned int>::iterator dit = (*dlm->decomposition)[d].begin(); dit != (*dlm->decomposition)[d].end(); ++dit) { 00111 unsigned int id = *dit; 00112 if(dit != (*dlm->decomposition)[d].begin()) 00113 name += ","; 00114 name += (*dnames)[id]; 00115 } 00116 name += ";"; 00117 } 00118 } 00119 if(dlm->embedding_type == DMLIBMESH_FIELD_EMBEDDING) { 00120 name += ":emb:var:"; 00121 enames = dlm->varnames; 00122 } 00123 if(dlm->embedding_type == DMLIBMESH_DOMAIN_EMBEDDING) { 00124 name += ":emb:block:"; 00125 enames = dlm->blocknames; 00126 } 00127 if(enames) { 00128 for(std::map<unsigned int, std::string>::iterator eit = enames->begin(); eit != enames->end(); ++eit) { 00129 std::string ename = eit->second; 00130 if(eit != enames->begin()) 00131 name += ","; 00132 name += ename; 00133 } 00134 name += ";"; 00135 } 00136 ierr = PetscObjectSetName((PetscObject)dm, name.c_str()); CHKERRQ(ierr); 00137 PetscFunctionReturn(0); 00138 } 00139 00140 #undef __FUNCT__ 00141 #define __FUNCT__ "DMLibMeshSetSystem" 00142 PetscErrorCode DMLibMeshSetSystem(DM dm, NonlinearImplicitSystem& sys) 00143 { 00144 PetscErrorCode ierr; 00145 PetscFunctionBegin; 00146 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 00147 PetscBool islibmesh; 00148 ierr = PetscObjectTypeCompare((PetscObject)dm, DMLIBMESH,&islibmesh); 00149 if(!islibmesh) SETERRQ2(((PetscObject)dm)->comm, PETSC_ERR_ARG_WRONG, "Got DM oftype %s, not of type %s", ((PetscObject)dm)->type_name, DMLIBMESH); 00150 00151 if(dm->setupcalled) SETERRQ(((PetscObject)dm)->comm, PETSC_ERR_ARG_WRONGSTATE, "Cannot reset the libMesh system after DM has been set up."); 00152 DM_libMesh *dlm = (DM_libMesh *)(dm->data); 00153 dlm->sys =&sys; 00154 /* Initially populate the sets of active blockids and varids using all of the 00155 existing blocks/variables (only variables are supported at the moment). */ 00156 DofMap& dofmap = dlm->sys->get_dof_map(); 00157 dlm->varids->clear(); 00158 dlm->varnames->clear(); 00159 for(unsigned int v = 0; v < dofmap.n_variables(); ++v) { 00160 std::string vname = dofmap.variable(v).name(); 00161 dlm->varids->insert(std::pair<std::string,unsigned int>(vname,v)); 00162 dlm->varnames->insert(std::pair<unsigned int,std::string>(v,vname)); 00163 } 00164 const MeshBase& mesh = dlm->sys->get_mesh(); 00165 dlm->blockids->clear(); 00166 dlm->blocknames->clear(); 00167 std::set<subdomain_id_type> blocks; 00168 /* The following effectively is a verbatim copy of MeshBase::n_subdomains(). */ 00169 // This requires an inspection on every processor 00170 parallel_only(); 00171 MeshBase::const_element_iterator el = mesh.active_elements_begin(); 00172 const MeshBase::const_element_iterator end = mesh.active_elements_end(); 00173 for (; el!=end; ++el) 00174 blocks.insert((*el)->subdomain_id()); 00175 // Some subdomains may only live on other processors 00176 CommWorld.set_union(blocks); 00177 00178 std::set<subdomain_id_type>::iterator bit = blocks.begin(); 00179 std::set<subdomain_id_type>::iterator bend = blocks.end(); 00180 if(bit == bend) SETERRQ(((PetscObject)dm)->comm, PETSC_ERR_PLIB, "No mesh blocks found."); 00181 00182 for(; bit != bend; ++bit) { 00183 subdomain_id_type bid = *bit; 00184 std::string bname = mesh.subdomain_name(bid); 00185 if(!bname.length()) { 00186 /* Block names are currently implemented for Exodus II meshes 00187 only, so we might have to make up our own block names and 00188 maintain our own mapping of block ids to names. 00189 */ 00190 std::ostringstream ss; 00191 ss << "dm" << bid; 00192 bname = ss.str(); 00193 } 00194 dlm->blockids->insert(std::pair<std::string,unsigned int>(bname,bid)); 00195 dlm->blocknames->insert(std::pair<unsigned int,std::string>(bid,bname)); 00196 } 00197 ierr = DMLibMeshSetUpName_Private(dm); CHKERRQ(ierr); 00198 PetscFunctionReturn(0); 00199 } 00200 00201 #undef __FUNCT__ 00202 #define __FUNCT__ "DMLibMeshGetSystem" 00203 PetscErrorCode DMLibMeshGetSystem(DM dm, NonlinearImplicitSystem*& sys) 00204 { 00205 PetscErrorCode ierr; 00206 PetscFunctionBegin; 00207 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 00208 PetscBool islibmesh; 00209 ierr = PetscObjectTypeCompare((PetscObject)dm, DMLIBMESH,&islibmesh); CHKERRQ(ierr); 00210 if(!islibmesh) SETERRQ2(((PetscObject)dm)->comm, PETSC_ERR_ARG_WRONG, "Got DM oftype %s, not of type %s", ((PetscObject)dm)->type_name, DMLIBMESH); 00211 DM_libMesh *dlm = (DM_libMesh *)(dm->data); 00212 sys = dlm->sys; 00213 PetscFunctionReturn(0); 00214 } 00215 00216 00217 #undef __FUNCT__ 00218 #define __FUNCT__ "DMCreateFieldDecomposition_libMesh" 00219 static PetscErrorCode DMCreateFieldDecomposition_libMesh(DM dm, PetscInt *len, char ***namelist, IS **islist, DM **dmlist) 00220 { 00221 PetscFunctionBegin; 00222 PetscErrorCode ierr; 00223 DM_libMesh *dlm = (DM_libMesh *)(dm->data); 00224 NonlinearImplicitSystem *sys = dlm->sys; 00225 IS emb; 00226 if(dlm->decomposition_type != DMLIBMESH_FIELD_DECOMPOSITION) PetscFunctionReturn(0); 00227 00228 *len = dlm->decomposition->size(); 00229 if(namelist) {ierr = PetscMalloc(*len*sizeof(char*), namelist); CHKERRQ(ierr);} 00230 if(islist) {ierr = PetscMalloc(*len*sizeof(IS), islist); CHKERRQ(ierr);} 00231 if(dmlist) {ierr = PetscMalloc(*len*sizeof(DM), dmlist); CHKERRQ(ierr);} 00232 DofMap& dofmap = dlm->sys->get_dof_map(); 00233 for(unsigned int d = 0; d < dlm->decomposition->size(); ++d) { 00234 std::set<unsigned int> dindices; 00235 std::string dname; 00236 std::map<std::string, unsigned int> dvarids; 00237 std::map<unsigned int, std::string> dvarnames; 00238 unsigned int dvcount = 0; 00239 for(std::set<unsigned int>::const_iterator dvit = (*dlm->decomposition)[d].begin(); dvit != (*dlm->decomposition)[d].end(); ++dvit){ 00240 unsigned int v = *dvit; 00241 std::string vname = (*dlm->varnames)[v]; 00242 dvarids.insert(std::pair<std::string, unsigned int>(vname,v)); 00243 dvarnames.insert(std::pair<unsigned int,std::string>(v,vname)); 00244 if(!dvcount) dname = vname; 00245 else dname += "_" + vname; 00246 ++dvcount; 00247 if(!islist) continue; 00248 /* Iterate only over this DM's blocks. */ 00249 for(std::map<std::string, unsigned int>::const_iterator bit = dlm->blockids->begin(); bit != dlm->blockids->end(); ++bit) { 00250 unsigned int b = bit->second; 00251 MeshBase::const_element_iterator el = sys->get_mesh().active_local_subdomain_elements_begin(b); 00252 MeshBase::const_element_iterator end_el = sys->get_mesh().active_local_subdomain_elements_end(b); 00253 for ( ; el != end_el; ++el) { 00254 const Elem* elem = *el; 00255 //unsigned int e_subdomain = elem->subdomain_id(); 00256 std::vector<unsigned int> evindices; 00257 // Get the degree of freedom indices for the given variable off the current element. 00258 dofmap.dof_indices(elem, evindices, v); 00259 for(unsigned int i = 0; i < evindices.size(); ++i) { 00260 unsigned int dof = evindices[i]; 00261 if(dof >= dofmap.first_dof() && dof < dofmap.end_dof()) /* might want to use variable_first/last_local_dof instead */ 00262 dindices.insert(dof); 00263 } 00264 } 00265 } 00266 } 00267 if(namelist) { 00268 ierr = PetscStrallocpy(dname.c_str(),(*namelist)+d); CHKERRQ(ierr); 00269 } 00270 if(islist) { 00271 IS dis; 00272 PetscInt *darray; 00273 ierr = PetscMalloc(sizeof(PetscInt)*dindices.size(), &darray); CHKERRQ(ierr); 00274 unsigned int i = 0; 00275 for(std::set<unsigned int>::const_iterator it = dindices.begin(); it != dindices.end(); ++it) { 00276 darray[i] = *it; 00277 ++i; 00278 } 00279 ierr = ISCreateGeneral(((PetscObject)dm)->comm, dindices.size(),darray, PETSC_OWN_POINTER, &dis); CHKERRQ(ierr); 00280 if(dlm->embedding) { 00281 /* Create a relative embedding into the parent's index space. */ 00282 ierr = ISMapFactorRight(dis,dlm->embedding, PETSC_TRUE, &emb); CHKERRQ(ierr); 00283 PetscInt elen, dlen; 00284 ierr = ISGetLocalSize(emb, &elen); CHKERRQ(ierr); 00285 ierr = ISGetLocalSize(dis, &dlen); CHKERRQ(ierr); 00286 if(elen != dlen) SETERRQ1(((PetscObject)dm)->comm, PETSC_ERR_PLIB, "Failed to embed subdomain %D", d); 00287 ierr = ISDestroy(&dis); CHKERRQ(ierr); 00288 dis = emb; 00289 } 00290 else { 00291 emb = dis; 00292 } 00293 (*islist)[d] = dis; 00294 } 00295 if(dmlist) { 00296 DM ddm; 00297 ierr = DMCreate(((PetscObject)dm)->comm, &ddm); CHKERRQ(ierr); 00298 ierr = DMSetType(ddm, DMLIBMESH); CHKERRQ(ierr); 00299 DM_libMesh *ddlm = (DM_libMesh*)(ddm->data); 00300 ddlm->sys = dlm->sys; 00301 /* copy over the block ids and names */ 00302 *ddlm->blockids = *dlm->blockids; 00303 *ddlm->blocknames = *dlm->blocknames; 00304 /* set the vars from the d-th part of the decomposition. */ 00305 *ddlm->varids = dvarids; 00306 *ddlm->varnames = dvarnames; 00307 ierr = PetscObjectReference((PetscObject)emb); CHKERRQ(ierr); 00308 ddlm->embedding = emb; 00309 ddlm->embedding_type = DMLIBMESH_FIELD_EMBEDDING; 00310 00311 ierr = DMLibMeshSetUpName_Private(ddm); CHKERRQ(ierr); 00312 ierr = DMSetFromOptions(ddm); CHKERRQ(ierr); 00313 (*dmlist)[d] = ddm; 00314 } 00315 } 00316 PetscFunctionReturn(0); 00317 } 00318 00319 #undef __FUNCT__ 00320 #define __FUNCT__ "DMCreateDomainDecomposition_libMesh" 00321 static PetscErrorCode DMCreateDomainDecomposition_libMesh(DM dm, PetscInt *len, char ***namelist, IS **innerislist, IS **outerislist, DM **dmlist) 00322 { 00323 PetscFunctionBegin; 00324 PetscErrorCode ierr; 00325 DM_libMesh *dlm = (DM_libMesh *)(dm->data); 00326 NonlinearImplicitSystem *sys = dlm->sys; 00327 IS emb; 00328 if(dlm->decomposition_type != DMLIBMESH_DOMAIN_DECOMPOSITION) PetscFunctionReturn(0); 00329 *len = dlm->decomposition->size(); 00330 if(namelist) {ierr = PetscMalloc(*len*sizeof(char*), namelist); CHKERRQ(ierr);} 00331 if(innerislist) {ierr = PetscMalloc(*len*sizeof(IS), innerislist); CHKERRQ(ierr);} 00332 if(outerislist) *outerislist = PETSC_NULL; /* FIX: allow mesh-based overlap. */ 00333 if(dmlist) {ierr = PetscMalloc(*len*sizeof(DM), dmlist); CHKERRQ(ierr);} 00334 for(unsigned int d = 0; d < dlm->decomposition->size(); ++d) { 00335 std::set<unsigned int> dindices; 00336 std::string dname; 00337 std::map<std::string, unsigned int> dblockids; 00338 std::map<unsigned int,std::string> dblocknames; 00339 unsigned int dbcount = 0; 00340 for(std::set<unsigned int>::const_iterator bit = (*dlm->decomposition)[d].begin(); bit != (*dlm->decomposition)[d].end(); ++bit){ 00341 unsigned int b = *bit; 00342 std::string bname = (*dlm->blocknames)[b]; 00343 dblockids.insert(std::pair<std::string, unsigned int>(bname,b)); 00344 dblocknames.insert(std::pair<unsigned int,std::string>(b,bname)); 00345 if(!dbcount) dname = bname; 00346 else dname += "_" + bname; 00347 ++dbcount; 00348 if(!innerislist) continue; 00349 MeshBase::const_element_iterator el = sys->get_mesh().active_local_subdomain_elements_begin(b); 00350 const MeshBase::const_element_iterator end_el = sys->get_mesh().active_local_subdomain_elements_end(b); 00351 for ( ; el != end_el; ++el) { 00352 const Elem* elem = *el; 00353 std::vector<unsigned int> evindices; 00354 /* Iterate only over this DM's variables. */ 00355 for(std::map<std::string, unsigned int>::const_iterator vit = dlm->varids->begin(); vit != dlm->varids->end(); ++vit) { 00356 unsigned int v = vit->second; 00357 // Get the degree of freedom indices for the given variable off the current element. 00358 sys->get_dof_map().dof_indices(elem, evindices, v); 00359 for(unsigned int i = 0; i < evindices.size(); ++i) { 00360 unsigned int dof = evindices[i]; 00361 if(dof >= sys->get_dof_map().first_dof() && dof < sys->get_dof_map().end_dof()) /* might want to use variable_first/last_local_dof instead */ 00362 dindices.insert(dof); 00363 } 00364 } 00365 } 00366 } 00367 if(namelist) { 00368 ierr = PetscStrallocpy(dname.c_str(),(*namelist)+d); CHKERRQ(ierr); 00369 } 00370 if(innerislist) { 00371 PetscInt *darray; 00372 IS dis; 00373 ierr = PetscMalloc(sizeof(PetscInt)*dindices.size(), &darray); CHKERRQ(ierr); 00374 unsigned int i = 0; 00375 for(std::set<unsigned int>::const_iterator it = dindices.begin(); it != dindices.end(); ++it) { 00376 darray[i] = *it; 00377 ++i; 00378 } 00379 ierr = ISCreateGeneral(((PetscObject)dm)->comm, dindices.size(),darray, PETSC_OWN_POINTER, &dis); CHKERRQ(ierr); 00380 if(dlm->embedding) { 00381 /* Create a relative embedding into the parent's index space. */ 00382 ierr = ISMapFactorRight(dis,dlm->embedding, PETSC_TRUE, &emb); CHKERRQ(ierr); 00383 PetscInt elen, dlen; 00384 ierr = ISGetLocalSize(emb, &elen); CHKERRQ(ierr); 00385 ierr = ISGetLocalSize(dis, &dlen); CHKERRQ(ierr); 00386 if(elen != dlen) SETERRQ1(((PetscObject)dm)->comm, PETSC_ERR_PLIB, "Failed to embed field %D", d); 00387 ierr = ISDestroy(&dis); CHKERRQ(ierr); 00388 dis = emb; 00389 } 00390 else { 00391 emb = dis; 00392 } 00393 if(innerislist) { 00394 ierr = PetscObjectReference((PetscObject)dis); CHKERRQ(ierr); 00395 (*innerislist)[d] = dis; 00396 } 00397 ierr = ISDestroy(&dis); CHKERRQ(ierr); 00398 } 00399 if(dmlist) { 00400 DM ddm; 00401 ierr = DMCreate(((PetscObject)dm)->comm, &ddm); CHKERRQ(ierr); 00402 ierr = DMSetType(ddm, DMLIBMESH); CHKERRQ(ierr); 00403 DM_libMesh *ddlm = (DM_libMesh*)(ddm->data); 00404 ddlm->sys = dlm->sys; 00405 /* copy over the varids and varnames */ 00406 *ddlm->varids = *dlm->varids; 00407 *ddlm->varnames = *dlm->varnames; 00408 /* set the blocks from the d-th part of the decomposition. */ 00409 *ddlm->blockids = dblockids; 00410 *ddlm->blocknames = dblocknames; 00411 ierr = PetscObjectReference((PetscObject)emb); CHKERRQ(ierr); 00412 ddlm->embedding = emb; 00413 ddlm->embedding_type = DMLIBMESH_DOMAIN_EMBEDDING; 00414 00415 ierr = DMLibMeshSetUpName_Private(ddm); CHKERRQ(ierr); 00416 ierr = DMSetFromOptions(ddm); CHKERRQ(ierr); 00417 (*dmlist)[d] = ddm; 00418 } 00419 } 00420 PetscFunctionReturn(0); 00421 } 00422 00423 00424 #undef __FUNCT__ 00425 #define __FUNCT__ "DMLibMeshCreateFieldDecompositionDM" 00426 PetscErrorCode DMLibMeshCreateFieldDecompositionDM(DM dm, PetscInt dnumber, PetscInt* dsizes, char*** dvarlists, DM* ddm) 00427 { 00428 PetscErrorCode ierr; 00429 PetscBool islibmesh; 00430 PetscFunctionBegin; 00431 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 00432 ierr = PetscObjectTypeCompare((PetscObject)dm, DMLIBMESH,&islibmesh); 00433 if(!islibmesh) SETERRQ2(((PetscObject)dm)->comm, PETSC_ERR_ARG_WRONG, "Got DM oftype %s, not of type %s", ((PetscObject)dm)->type_name, DMLIBMESH); 00434 if(dnumber < 0) SETERRQ1(((PetscObject)dm)->comm, PETSC_ERR_ARG_WRONG, "Negative number %D of decomposition parts", dnumber); 00435 PetscValidPointer(ddm,5); 00436 DM_libMesh *dlm = (DM_libMesh *)(dm->data); 00437 ierr = DMCreate(((PetscObject)dm)->comm, ddm); CHKERRQ(ierr); 00438 ierr = DMSetType(*ddm, DMLIBMESH); CHKERRQ(ierr); 00439 DM_libMesh *ddlm = (DM_libMesh *)((*ddm)->data); 00440 ddlm->sys = dlm->sys; 00441 ddlm->varids = dlm->varids; 00442 ddlm->varnames = dlm->varnames; 00443 ddlm->blockids = dlm->blockids; 00444 ddlm->blocknames = dlm->blocknames; 00445 ddlm->decomposition = new(std::vector<std::set<unsigned int> >); 00446 ddlm->decomposition_type = DMLIBMESH_FIELD_DECOMPOSITION; 00447 if(dnumber) { 00448 for(PetscInt d = 0; d < dnumber; ++d) { 00449 if(dsizes[d] < 0) SETERRQ2(((PetscObject)dm)->comm, PETSC_ERR_ARG_WRONG, "Negative size %D of decomposition part %D", dsizes[d],d); 00450 ddlm->decomposition->push_back(std::set<unsigned int>()); 00451 for(PetscInt v = 0; v < dsizes[d]; ++v) { 00452 std::string vname(dvarlists[d][v]); 00453 std::map<std::string, unsigned int>::const_iterator vit = dlm->varids->find(vname); 00454 if(vit == dlm->varids->end()) 00455 SETERRQ3(((PetscObject)dm)->comm, PETSC_ERR_ARG_WRONG, "Variable %D on the %D-th list with name %s is not owned by this DM", v, d, dvarlists[d][v]); 00456 unsigned int vid = vit->second; 00457 (*ddlm->decomposition)[d].insert(vid); 00458 } 00459 } 00460 } 00461 else { /* Empty splits indicate default: split all variables with one per split. */ 00462 PetscInt d = 0; 00463 for(std::map<std::string, unsigned int>::const_iterator vit = ddlm->varids->begin(); vit != ddlm->varids->end(); ++vit) { 00464 ddlm->decomposition->push_back(std::set<unsigned int>()); 00465 unsigned int vid = vit->second; 00466 std::string vname = vit->first; 00467 (*ddlm->decomposition)[d].insert(vid); 00468 ++d; 00469 } 00470 } 00471 ierr = DMLibMeshSetUpName_Private(*ddm); CHKERRQ(ierr); 00472 ierr = DMSetFromOptions(*ddm); CHKERRQ(ierr); 00473 ierr = DMSetUp(*ddm); CHKERRQ(ierr); 00474 PetscFunctionReturn(0); 00475 } 00476 00477 #undef __FUNCT__ 00478 #define __FUNCT__ "DMLibMeshCreateDomainDecompositionDM" 00479 PetscErrorCode DMLibMeshCreateDomainDecompositionDM(DM dm, PetscInt dnumber, PetscInt* dsizes, char*** dblocklists, DM* ddm) 00480 { 00481 PetscErrorCode ierr; 00482 PetscBool islibmesh; 00483 PetscFunctionBegin; 00484 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 00485 ierr = PetscObjectTypeCompare((PetscObject)dm, DMLIBMESH,&islibmesh); 00486 if(!islibmesh) SETERRQ2(((PetscObject)dm)->comm, PETSC_ERR_ARG_WRONG, "Got DM oftype %s, not of type %s", ((PetscObject)dm)->type_name, DMLIBMESH); 00487 if(dnumber < 0) SETERRQ1(((PetscObject)dm)->comm, PETSC_ERR_ARG_WRONG, "Negative number %D of decomposition parts", dnumber); 00488 PetscValidPointer(ddm,5); 00489 DM_libMesh *dlm = (DM_libMesh *)(dm->data); 00490 ierr = DMCreate(((PetscObject)dm)->comm, ddm); CHKERRQ(ierr); 00491 ierr = DMSetType(*ddm, DMLIBMESH); CHKERRQ(ierr); 00492 DM_libMesh *ddlm = (DM_libMesh *)((*ddm)->data); 00493 ddlm->sys = dlm->sys; 00494 ddlm->varids = dlm->varids; 00495 ddlm->varnames = dlm->varnames; 00496 ddlm->blockids = dlm->blockids; 00497 ddlm->blocknames = dlm->blocknames; 00498 ddlm->decomposition = new(std::vector<std::set<unsigned int> >); 00499 ddlm->decomposition_type = DMLIBMESH_DOMAIN_DECOMPOSITION; 00500 if(dnumber) { 00501 for(PetscInt d = 0; d < dnumber; ++d) { 00502 if(dsizes[d] < 0) SETERRQ2(((PetscObject)dm)->comm, PETSC_ERR_ARG_WRONG, "Negative size %D of decomposition part %D", dsizes[d],d); 00503 ddlm->decomposition->push_back(std::set<unsigned int>()); 00504 for(PetscInt b = 0; b < dsizes[d]; ++b) { 00505 std::string bname(dblocklists[d][b]); 00506 std::map<std::string, unsigned int>::const_iterator bit = dlm->blockids->find(bname); 00507 if(bit == dlm->blockids->end()) 00508 SETERRQ3(((PetscObject)dm)->comm, PETSC_ERR_ARG_WRONG, "Block %D on the %D-th list with name %s is not owned by this DM", b, d, dblocklists[d][b]); 00509 unsigned int bid = bit->second; 00510 (*ddlm->decomposition)[d].insert(bid); 00511 } 00512 } 00513 } 00514 else { /* Empty splits indicate default: split all blocks with one per split. */ 00515 PetscInt d = 0; 00516 for(std::map<std::string, unsigned int>::const_iterator bit = ddlm->blockids->begin(); bit != ddlm->blockids->end(); ++bit) { 00517 ddlm->decomposition->push_back(std::set<unsigned int>()); 00518 unsigned int bid = bit->second; 00519 std::string bname = bit->first; 00520 (*ddlm->decomposition)[d].insert(bid); 00521 ++d; 00522 } 00523 } 00524 ierr = DMLibMeshSetUpName_Private(*ddm); CHKERRQ(ierr); 00525 ierr = DMSetFromOptions(*ddm); CHKERRQ(ierr); 00526 ierr = DMSetUp(*ddm); CHKERRQ(ierr); 00527 PetscFunctionReturn(0); 00528 } 00529 00530 struct token { 00531 const char* s; 00532 struct token *next; 00533 }; 00534 #undef __FUNCT__ 00535 #define __FUNCT__ "DMLibMeshParseDecompositionDescriptor_Private" 00536 static PetscErrorCode DMLibMeshParseDecompositionDescriptor_Private(DM dm, const char* ddesc, PetscInt* dtype, PetscInt* dcount, PetscInt** dsizes, char ****dlists) 00537 { 00538 PetscFunctionBegin; 00539 PetscErrorCode ierr; 00540 PetscBool eq; 00541 char *s0, *s, *ss; 00542 struct token *llfirst = PETSC_NULL, *lllast = PETSC_NULL, *tok; 00543 PetscInt stcount = 0, brcount = 0, d, i; 00544 size_t len0, count; 00545 00546 /* 00547 Parse the decomposition descriptor. 00548 Decomposition names could be of one of two forms: 00549 var:v1,v2;v3,v4;v4,v5; 00550 block:b1,b2;b3,b4;b4,b5; 00551 resulting in an overlapping decomposition that groups 00552 variables (v1,v2), (v3,v4), (v4,v5) or 00553 blocks (b1,b2), (b3,b4), (b4,b5). 00554 */ 00555 /* Copy the descriptor so that we can manipulate it in place. */ 00556 ierr = PetscStrallocpy(ddesc,&s0); CHKERRQ(ierr); 00557 ierr = PetscStrlen(s0, &len0) ; CHKERRQ(ierr); 00558 ierr = PetscStrstr(s0,":",&ss); CHKERRQ(ierr); 00559 if(!ss) { 00560 ss = s0+len0; 00561 } 00562 else { 00563 *ss = 0; 00564 } 00565 ierr = PetscStrcmp(s0,"var",&eq); CHKERRQ(ierr); 00566 if(eq) { 00567 *dtype=DMLIBMESH_FIELD_DECOMPOSITION; 00568 } 00569 else { 00570 ierr = PetscStrcmp(s0,"block",&eq);CHKERRQ(ierr); 00571 if(!eq) 00572 SETERRQ1(((PetscObject)dm)->comm, PETSC_ERR_ARG_WRONG, "Could not determine decomposition type from descriptor: %s\n", ddesc); CHKERRQ(ierr); 00573 *dtype=DMLIBMESH_DOMAIN_DECOMPOSITION; 00574 } 00575 ierr = PetscStrlen(s0,&count); CHKERRQ(ierr); 00576 while(count < len0) { 00577 struct token *st, *br; 00578 ++ss; ++count; 00579 s=ss; 00580 while(*ss && *ss != ',' && *ss != ';') { 00581 ++ss; ++count; 00582 } 00583 st = PETSC_NULL; br = PETSC_NULL; 00584 if(*ss) { 00585 /* 00586 Found a separator, or a break. 00587 Add an appropriate token to the list. 00588 A token separator ',' produces no token. 00589 */ 00590 if(*ss == ';') { 00591 /* Create a break token: a token with a null string. */ 00592 ierr = PetscNew(struct token, &br); CHKERRQ(ierr); 00593 } 00594 *ss = 0; 00595 if(s != ss) { 00596 /* A nonempty string. */ 00597 ierr = PetscNew(struct token, &st); CHKERRQ(ierr); 00598 st->s = s; /* The string will be properly copied below. */ 00599 } 00600 /* Add the new tokens to the list. */ 00601 if(st) { 00602 if(!lllast) { 00603 llfirst = lllast = st; 00604 } 00605 else { 00606 lllast->next = st; lllast = st; 00607 } 00608 } 00609 if(br) { 00610 if(!lllast) { 00611 llfirst = lllast = br; 00612 } 00613 else { 00614 lllast->next = br; lllast = br; 00615 } 00616 } 00617 } 00618 } 00619 /* The result of parsing is in the linked list ll. */ 00620 /* Count up the strings and the breaks. */ 00621 tok = llfirst; 00622 while(tok) { 00623 if(tok->s) 00624 ++stcount; 00625 else 00626 ++brcount; 00627 tok = tok->next; 00628 } 00629 /* Allocate the space for the output. */ 00630 *dcount = brcount; 00631 ierr = PetscMalloc(*dcount*sizeof(PetscInt), dsizes); CHKERRQ(ierr); 00632 ierr = PetscMalloc(*dcount*sizeof(char**), dlists); CHKERRQ(ierr); 00633 for(d = 0; d < *dcount; ++d) (*dsizes)[d] = 0; 00634 tok = llfirst; d = 0; 00635 while(tok) { 00636 if(tok->s) 00637 ++(*dsizes)[d]; 00638 else 00639 ++d; 00640 tok = tok->next; 00641 } 00642 for(d = 0; d < *dcount; ++d) { 00643 ierr = PetscMalloc(sizeof(char**)*(*dsizes)[d], (*dlists)+d); CHKERRQ(ierr); 00644 } 00645 /* Now copy strings and destroy tokens. */ 00646 tok = llfirst; d = 0; i = 0; 00647 while(tok) { 00648 if(tok->s) { 00649 ierr = PetscStrallocpy(tok->s, (*dlists)[d]+i); CHKERRQ(ierr); 00650 ++i; 00651 } 00652 else { 00653 ++d; 00654 i = 0; 00655 } 00656 llfirst = tok; 00657 tok = tok->next; 00658 ierr = PetscFree(llfirst); CHKERRQ(ierr); 00659 } 00660 /* Deallocate workspace. */ 00661 ierr = PetscFree(s0); CHKERRQ(ierr); 00662 PetscFunctionReturn(0); 00663 } 00664 00665 #undef __FUNCT__ 00666 #define __FUNCT__ "DMCreateFieldDecompositionDM_libMesh" 00667 static PetscErrorCode DMCreateFieldDecompositionDM_libMesh(DM dm, const char* ddesc, DM *ddm) 00668 { 00669 PetscFunctionBegin; 00670 PetscErrorCode ierr; 00671 PetscInt dtype, dcount, *dsizes; 00672 char ***dlists; 00673 PetscFunctionBegin; 00674 *ddm = PETSC_NULL; 00675 ierr = DMLibMeshParseDecompositionDescriptor_Private(dm,ddesc,&dtype,&dcount,&dsizes,&dlists); CHKERRQ(ierr); 00676 if(dtype == DMLIBMESH_FIELD_DECOMPOSITION){ 00677 ierr = DMLibMeshCreateFieldDecompositionDM(dm,dcount,dsizes,dlists,ddm); CHKERRQ(ierr); 00678 } 00679 else SETERRQ1(((PetscObject)dm)->comm, PETSC_ERR_PLIB, "Uexpected unknown decomposition type for field decomposition descriptor %s", ddesc); 00680 PetscFunctionReturn(0); 00681 } 00682 00683 #undef __FUNCT__ 00684 #define __FUNCT__ "DMCreateDomainDecompositionDM_libMesh" 00685 static PetscErrorCode DMCreateDomainDecompositionDM_libMesh(DM dm, const char* ddesc, DM *ddm) 00686 { 00687 PetscFunctionBegin; 00688 PetscErrorCode ierr; 00689 PetscInt dtype, dcount, *dsizes; 00690 char ***dlists; 00691 PetscFunctionBegin; 00692 *ddm = PETSC_NULL; 00693 ierr = DMLibMeshParseDecompositionDescriptor_Private(dm,ddesc,&dtype,&dcount,&dsizes,&dlists); CHKERRQ(ierr); 00694 if(dtype == DMLIBMESH_DOMAIN_DECOMPOSITION) { 00695 ierr = DMLibMeshCreateDomainDecompositionDM(dm,dcount,dsizes,dlists,ddm); CHKERRQ(ierr); 00696 } 00697 else SETERRQ1(((PetscObject)dm)->comm, PETSC_ERR_PLIB, "Uexpected unknown decomposition type for domain decomposition descriptor %s", ddesc); 00698 PetscFunctionReturn(0); 00699 } 00700 00701 #undef __FUNCT__ 00702 #define __FUNCT__ "DMFunction_libMesh" 00703 static PetscErrorCode DMFunction_libMesh(DM dm, Vec x, Vec r) 00704 { 00705 PetscErrorCode ierr; 00706 PetscFunctionBegin; 00707 libmesh_assert(x); 00708 libmesh_assert(r); 00709 00710 NonlinearImplicitSystem* _sys; 00711 ierr = DMLibMeshGetSystem(dm, _sys); CHKERRQ(ierr); 00712 NonlinearImplicitSystem& sys = *_sys; 00713 PetscVector<Number>& X_sys = *libmesh_cast_ptr<PetscVector<Number>* >(sys.solution.get()); 00714 PetscVector<Number>& R_sys = *libmesh_cast_ptr<PetscVector<Number>* >(sys.rhs); 00715 PetscVector<Number> X_global(x), R(r); 00716 00717 // Use the systems update() to get a good local version of the parallel solution 00718 X_global.swap(X_sys); 00719 R.swap(R_sys); 00720 00721 _sys->get_dof_map().enforce_constraints_exactly(*_sys); 00722 _sys->update(); 00723 00724 // Swap back 00725 X_global.swap(X_sys); 00726 R.swap(R_sys); 00727 R.zero(); 00728 00729 // if the user has provided both function pointers and objects only the pointer 00730 // will be used, so catch that as an error 00731 if (_sys->nonlinear_solver->residual && _sys->nonlinear_solver->residual_object) 00732 { 00733 libMesh::err << "ERROR: cannot specifiy both a function and object to compute the Residual!" << std::endl; 00734 libmesh_error(); 00735 } 00736 00737 if (_sys->nonlinear_solver->matvec && _sys->nonlinear_solver->residual_and_jacobian_object) 00738 { 00739 libMesh::err << "ERROR: cannot specifiy both a function and object to compute the combined Residual & Jacobian!" << std::endl; 00740 libmesh_error(); 00741 } 00742 00743 if (_sys->nonlinear_solver->residual != NULL) 00744 _sys->nonlinear_solver->residual(*(_sys->current_local_solution.get()), R, *_sys); 00745 00746 else if (_sys->nonlinear_solver->residual_object != NULL) 00747 _sys->nonlinear_solver->residual_object->residual(*(_sys->current_local_solution.get()), R, *_sys); 00748 00749 else if (_sys->nonlinear_solver->matvec != NULL) 00750 _sys->nonlinear_solver->matvec(*(_sys->current_local_solution.get()), &R, NULL, *_sys); 00751 00752 else if (_sys->nonlinear_solver->residual_and_jacobian_object != NULL) 00753 _sys->nonlinear_solver->residual_and_jacobian_object->residual_and_jacobian(*(_sys->current_local_solution.get()), &R, NULL, *_sys); 00754 00755 else 00756 libmesh_error(); 00757 00758 R.close(); 00759 X_global.close(); 00760 PetscFunctionReturn(0); 00761 } 00762 00763 00764 00765 00766 #undef __FUNCT__ 00767 #define __FUNCT__ "DMJacobian_libMesh" 00768 static PetscErrorCode DMJacobian_libMesh(DM dm, Vec x, Mat jac, Mat pc, MatStructure *msflag) 00769 { 00770 PetscErrorCode ierr; 00771 PetscFunctionBegin; 00772 NonlinearImplicitSystem* _sys; 00773 ierr = DMLibMeshGetSystem(dm, _sys); CHKERRQ(ierr); 00774 NonlinearImplicitSystem& sys = *_sys; 00775 00776 PetscMatrix<Number> the_pc(pc); 00777 PetscMatrix<Number> Jac(jac); 00778 PetscVector<Number>& X_sys = *libmesh_cast_ptr<PetscVector<Number>*>(sys.solution.get()); 00779 PetscMatrix<Number>& Jac_sys = *libmesh_cast_ptr<PetscMatrix<Number>*>(sys.matrix); 00780 PetscVector<Number> X_global(x); 00781 00782 // Set the dof maps 00783 the_pc.attach_dof_map(sys.get_dof_map()); 00784 Jac.attach_dof_map(sys.get_dof_map()); 00785 00786 // Use the systems update() to get a good local version of the parallel solution 00787 X_global.swap(X_sys); 00788 Jac.swap(Jac_sys); 00789 00790 sys.get_dof_map().enforce_constraints_exactly(sys); 00791 sys.update(); 00792 00793 X_global.swap(X_sys); 00794 Jac.swap(Jac_sys); 00795 00796 the_pc.zero(); 00797 00798 // if the user has provided both function pointers and objects only the pointer 00799 // will be used, so catch that as an error 00800 if (sys.nonlinear_solver->jacobian && sys.nonlinear_solver->jacobian_object) 00801 { 00802 libMesh::err << "ERROR: cannot specifiy both a function and object to compute the Jacobian!" << std::endl; 00803 libmesh_error(); 00804 } 00805 00806 if (sys.nonlinear_solver->matvec && sys.nonlinear_solver->residual_and_jacobian_object) 00807 { 00808 libMesh::err << "ERROR: cannot specifiy both a function and object to compute the combined Residual & Jacobian!" << std::endl; 00809 libmesh_error(); 00810 } 00811 00812 if (sys.nonlinear_solver->jacobian != NULL) 00813 sys.nonlinear_solver->jacobian(*(sys.current_local_solution.get()), the_pc, sys); 00814 00815 else if (sys.nonlinear_solver->jacobian_object != NULL) 00816 sys.nonlinear_solver->jacobian_object->jacobian(*(sys.current_local_solution.get()), the_pc, sys); 00817 00818 else if (sys.nonlinear_solver->matvec != NULL) 00819 sys.nonlinear_solver->matvec(*(sys.current_local_solution.get()), NULL, &the_pc, sys); 00820 00821 else if (sys.nonlinear_solver->residual_and_jacobian_object != NULL) 00822 sys.nonlinear_solver->residual_and_jacobian_object->residual_and_jacobian(*(sys.current_local_solution.get()), NULL, &the_pc, sys); 00823 00824 else 00825 libmesh_error(); 00826 00827 the_pc.close(); 00828 Jac.close(); 00829 X_global.close(); 00830 00831 *msflag = SAME_NONZERO_PATTERN; 00832 PetscFunctionReturn(0); 00833 } 00834 00835 00836 #undef __FUNCT__ 00837 #define __FUNCT__ "DMVariableBounds_libMesh" 00838 static PetscErrorCode DMVariableBounds_libMesh(DM dm, Vec xl, Vec xu) 00839 { 00840 PetscErrorCode ierr; 00841 NonlinearImplicitSystem* _sys; 00842 ierr = DMLibMeshGetSystem(dm, _sys); CHKERRQ(ierr); 00843 NonlinearImplicitSystem& sys = *_sys; 00844 PetscVector<Number> XL(xl); 00845 PetscVector<Number> XU(xu); 00846 PetscFunctionBegin; 00847 00848 ierr = VecSet(xl, SNES_VI_NINF); CHKERRQ(ierr); 00849 ierr = VecSet(xu, SNES_VI_INF); CHKERRQ(ierr); 00850 if (sys.nonlinear_solver->bounds != NULL) 00851 sys.nonlinear_solver->bounds(XL,XU,sys); 00852 else if (sys.nonlinear_solver->bounds_object != NULL) 00853 sys.nonlinear_solver->bounds_object->bounds(XL,XU, sys); 00854 else 00855 SETERRQ(((PetscObject)dm)->comm, PETSC_ERR_ARG_WRONG, "No bounds calculation in this libMesh object"); 00856 00857 PetscFunctionReturn(0); 00858 } 00859 00860 00861 #undef __FUNCT__ 00862 #define __FUNCT__ "DMCreateGlobalVector_libMesh" 00863 static PetscErrorCode DMCreateGlobalVector_libMesh(DM dm, Vec *x) 00864 { 00865 PetscFunctionBegin; 00866 PetscErrorCode ierr; 00867 DM_libMesh *dlm = (DM_libMesh *)(dm->data); 00868 PetscBool eq; 00869 00870 ierr = PetscObjectTypeCompare((PetscObject)dm, DMLIBMESH, &eq); CHKERRQ(ierr); 00871 00872 if (!eq) 00873 SETERRQ2(((PetscObject)dm)->comm, PETSC_ERR_ARG_WRONG, "DM of type %s, not of type %s", ((PetscObject)dm)->type, DMLIBMESH); 00874 00875 if (!dlm->sys) 00876 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONGSTATE, "No libMesh system set for DM_libMesh"); 00877 00878 NumericVector<Number>* nv = (dlm->sys->solution).get(); 00879 PetscVector<Number>* pv = dynamic_cast<PetscVector<Number>*>(nv); 00880 Vec v = pv->vec(); 00881 /* Unfortunately, currently this does not produce a ghosted vector, so nonlinear subproblem solves aren't going to be easily available. 00882 Should work fine for getting vectors out for linear subproblem solvers. */ 00883 if(dlm->embedding) { 00884 PetscInt n; 00885 ierr = VecCreate(((PetscObject)v)->comm, x); CHKERRQ(ierr); 00886 ierr = ISGetLocalSize(dlm->embedding, &n); CHKERRQ(ierr); 00887 ierr = VecSetSizes(*x,n,PETSC_DETERMINE); CHKERRQ(ierr); 00888 ierr = VecSetType(*x,((PetscObject)v)->type_name); CHKERRQ(ierr); 00889 ierr = VecSetFromOptions(*x); CHKERRQ(ierr); 00890 ierr = VecSetUp(*x); CHKERRQ(ierr); 00891 } 00892 else { 00893 ierr = VecDuplicate(v,x); CHKERRQ(ierr); 00894 } 00895 ierr = PetscObjectCompose((PetscObject)*x,"DM",(PetscObject)dm); CHKERRQ(ierr); 00896 PetscFunctionReturn(0); 00897 } 00898 00899 00900 00901 00902 #undef __FUNCT__ 00903 #define __FUNCT__ "DMCreateMatrix_libMesh" 00904 static PetscErrorCode DMCreateMatrix_libMesh(DM dm, const MatType, Mat *A) 00905 { 00906 PetscFunctionBegin; 00907 PetscErrorCode ierr; 00908 DM_libMesh *dlm = (DM_libMesh *)(dm->data); 00909 PetscBool eq; 00910 00911 ierr = PetscObjectTypeCompare((PetscObject)dm, DMLIBMESH, &eq); CHKERRQ(ierr); 00912 00913 if (!eq) 00914 SETERRQ2(((PetscObject)dm)->comm, PETSC_ERR_ARG_WRONG, "DM of type %s, not of type %s", ((PetscObject)dm)->type, DMLIBMESH); 00915 00916 if (!dlm->sys) 00917 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONGSTATE, "No libMesh system set for DM_libMesh"); 00918 00919 *A = (dynamic_cast<PetscMatrix<Number>*>(dlm->sys->matrix))->mat(); 00920 ierr = PetscObjectReference((PetscObject)(*A)); CHKERRQ(ierr); 00921 PetscFunctionReturn(0); 00922 } 00923 00924 00925 #undef __FUNCT__ 00926 #define __FUNCT__ "DMView_libMesh" 00927 static PetscErrorCode DMView_libMesh(DM dm, PetscViewer viewer) 00928 { 00929 PetscErrorCode ierr; 00930 PetscBool isascii; 00931 const char *name, *prefix; 00932 DM_libMesh *dlm = (DM_libMesh*)dm->data; 00933 PetscFunctionBegin; 00934 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii); CHKERRQ(ierr); 00935 if(isascii) { 00936 ierr = PetscObjectGetName((PetscObject)dm, &name); CHKERRQ(ierr); 00937 ierr = PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix); CHKERRQ(ierr); 00938 ierr = PetscViewerASCIIPrintf(viewer, "DM libMesh with name %s and prefix %s\n", name, prefix); CHKERRQ(ierr); 00939 ierr = PetscViewerASCIIPrintf(viewer, "blocks:", name, prefix); CHKERRQ(ierr); 00940 std::map<std::string,unsigned int>::iterator bit = dlm->blockids->begin(); 00941 std::map<std::string,unsigned int>::const_iterator bend = dlm->blockids->end(); 00942 for(; bit != bend; ++bit) { 00943 ierr = PetscViewerASCIIPrintf(viewer, "(%s,%D) ", bit->first.c_str(), bit->second); CHKERRQ(ierr); 00944 } 00945 ierr = PetscViewerASCIIPrintf(viewer, "\n"); CHKERRQ(ierr); 00946 ierr = PetscViewerASCIIPrintf(viewer, "variables:", name, prefix); CHKERRQ(ierr); 00947 std::map<std::string,unsigned int>::iterator vit = dlm->varids->begin(); 00948 std::map<std::string,unsigned int>::const_iterator vend = dlm->varids->end(); 00949 for(; vit != vend; ++vit) { 00950 ierr = PetscViewerASCIIPrintf(viewer, "(%s,%D) ", vit->first.c_str(), vit->second); CHKERRQ(ierr); 00951 } 00952 ierr = PetscViewerASCIIPrintf(viewer, "\n"); CHKERRQ(ierr); 00953 if(dlm->decomposition_type == DMLIBMESH_NO_DECOMPOSITION) { 00954 ierr = PetscViewerASCIIPrintf(viewer, "No decomposition\n"); CHKERRQ(ierr); 00955 } 00956 else { 00957 if(dlm->decomposition_type == DMLIBMESH_FIELD_DECOMPOSITION) { 00958 ierr = PetscViewerASCIIPrintf(viewer, "Field decomposition by variable: "); CHKERRQ(ierr); 00959 } 00960 else if(dlm->decomposition_type == DMLIBMESH_DOMAIN_DECOMPOSITION) { 00961 ierr = PetscViewerASCIIPrintf(viewer, "Domain decomposition by block: "); CHKERRQ(ierr); 00962 } 00963 else SETERRQ1(((PetscObject)dm)->comm, PETSC_ERR_PLIB, "Unexpected decomposition type: %D", dlm->decomposition_type); 00964 /* FIX: decompositions might have different sizes and components on different ranks. */ 00965 for(unsigned int d = 0; d < dlm->decomposition->size(); ++d) { 00966 std::set<unsigned int>::iterator dbegin = (*dlm->decomposition)[d].begin(); 00967 std::set<unsigned int>::iterator dit = (*dlm->decomposition)[d].begin(); 00968 std::set<unsigned int>::iterator dend = (*dlm->decomposition)[d].end(); 00969 for(; dit != dend; ++dit) { 00970 if(dit != dbegin) { 00971 ierr = PetscViewerASCIIPrintf(viewer, ","); CHKERRQ(ierr); 00972 } 00973 ierr = PetscViewerASCIIPrintf(viewer, "%D", *dit); CHKERRQ(ierr); 00974 } 00975 ierr = PetscViewerASCIIPrintf(viewer, ";"); CHKERRQ(ierr); 00976 } 00977 ierr = PetscViewerASCIIPrintf(viewer, "\n"); CHKERRQ(ierr); 00978 } 00979 } 00980 00981 PetscFunctionReturn(0); 00982 } 00983 00984 #undef __FUNCT__ 00985 #define __FUNCT__ "DMSetUp_libMesh" 00986 static PetscErrorCode DMSetUp_libMesh(DM dm) 00987 { 00988 PetscFunctionBegin; 00989 PetscErrorCode ierr; 00990 DM_libMesh *dlm = (DM_libMesh *)(dm->data); 00991 PetscBool eq; 00992 00993 ierr = PetscObjectTypeCompare((PetscObject)dm, DMLIBMESH, &eq); CHKERRQ(ierr); 00994 00995 if (!eq) 00996 SETERRQ2(((PetscObject)dm)->comm, PETSC_ERR_ARG_WRONG, "DM of type %s, not of type %s", ((PetscObject)dm)->type, DMLIBMESH); 00997 00998 if (!dlm->sys) 00999 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONGSTATE, "No libMesh system set for DM_libMesh"); 01000 /* 01001 Do not evaluate function, Jacobian or bounds for an embedded DM -- the subproblem might not have enough information for that. 01002 */ 01003 if(!dlm->embedding) { 01004 ierr = DMSetFunction(dm, DMFunction_libMesh); CHKERRQ(ierr); 01005 ierr = DMSetJacobian(dm, DMJacobian_libMesh); CHKERRQ(ierr); 01006 if (dlm->sys->nonlinear_solver->bounds || dlm->sys->nonlinear_solver->bounds_object) 01007 ierr = DMSetVariableBounds(dm, DMVariableBounds_libMesh); CHKERRQ(ierr); 01008 01009 } 01010 else { 01011 /* 01012 Fow now we don't implement even these, although a linear "Dirichlet" subproblem is well-defined. 01013 Creating the submatrix, however, might require extracting the submatrix preallocation from an unassembled matrix. 01014 */ 01015 dm->ops->createglobalvector = 0; 01016 dm->ops->creatematrix = 0; 01017 } 01018 PetscFunctionReturn(0); 01019 } 01020 01021 01022 01023 01024 #undef __FUNCT__ 01025 #define __FUNCT__ "DMDestroy_libMesh" 01026 static PetscErrorCode DMDestroy_libMesh(DM dm) 01027 { 01028 DM_libMesh *dlm = (DM_libMesh*)(dm->data); 01029 PetscErrorCode ierr; 01030 PetscFunctionBegin; 01031 delete dlm->varids; 01032 delete dlm->varnames; 01033 delete dlm->blockids; 01034 delete dlm->blocknames; 01035 if(dlm->decomposition) 01036 delete dlm->decomposition; 01037 ierr = ISDestroy(&dlm->embedding); CHKERRQ(ierr); 01038 ierr = PetscFree(dm->data); CHKERRQ(ierr); 01039 01040 PetscFunctionReturn(0); 01041 } 01042 01043 01044 #undef __FUNCT__ 01045 #define __FUNCT__ "DMCreateLibMesh" 01046 PetscErrorCode DMCreateLibMesh(MPI_Comm comm, NonlinearImplicitSystem& sys, DM *dm) 01047 { 01048 PetscErrorCode ierr; 01049 PetscFunctionBegin; 01050 ierr = DMCreate(comm, dm); CHKERRQ(ierr); 01051 ierr = DMSetType(*dm, DMLIBMESH); CHKERRQ(ierr); 01052 ierr = DMLibMeshSetSystem(*dm, sys); CHKERRQ(ierr); 01053 PetscFunctionReturn(0); 01054 } 01055 01056 EXTERN_C_BEGIN 01057 #undef __FUNCT__ 01058 #define __FUNCT__ "DMCreate_libMesh" 01059 PetscErrorCode DMCreate_libMesh(DM dm) 01060 { 01061 PetscErrorCode ierr; 01062 DM_libMesh *dlm; 01063 01064 PetscFunctionBegin; 01065 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 01066 ierr = PetscNewLog(dm,DM_libMesh,&dlm);CHKERRQ(ierr); 01067 dm->data = dlm; 01068 01069 dlm->varids = new(std::map<std::string, unsigned int>); 01070 dlm->blockids = new(std::map<std::string, unsigned int>); 01071 dlm->varnames = new(std::map<unsigned int, std::string>); 01072 dlm->blocknames = new(std::map<unsigned int, std::string>); 01073 dlm->decomposition = PETSC_NULL; 01074 dlm->decomposition_type = DMLIBMESH_NO_DECOMPOSITION; 01075 01076 dm->ops->createglobalvector = DMCreateGlobalVector_libMesh; 01077 dm->ops->createlocalvector = 0; // DMCreateLocalVector_libMesh; 01078 dm->ops->getcoloring = 0; // DMGetColoring_libMesh; 01079 dm->ops->creatematrix = DMCreateMatrix_libMesh; 01080 dm->ops->createinterpolation= 0; // DMCreateInterpolation_libMesh; 01081 01082 dm->ops->refine = 0; // DMRefine_libMesh; 01083 dm->ops->coarsen = 0; // DMCoarsen_libMesh; 01084 dm->ops->getinjection = 0; // DMGetInjection_libMesh; 01085 dm->ops->getaggregates = 0; // DMGetAggregates_libMesh; 01086 01087 dm->ops->createfielddecompositiondm = DMCreateFieldDecompositionDM_libMesh; 01088 dm->ops->createfielddecomposition = DMCreateFieldDecomposition_libMesh; 01089 dm->ops->createdomaindecompositiondm = DMCreateDomainDecompositionDM_libMesh; 01090 dm->ops->createdomaindecomposition = DMCreateDomainDecomposition_libMesh; 01091 01092 dm->ops->destroy = DMDestroy_libMesh; 01093 dm->ops->view = DMView_libMesh; 01094 dm->ops->setfromoptions = 0; // DMSetFromOptions_libMesh; 01095 dm->ops->setup = DMSetUp_libMesh; 01096 01097 PetscFunctionReturn(0); 01098 } 01099 EXTERN_C_END 01100 01101 01102 #endif // #if !PETSC_VERSION_LESS_THAN(3,3,0)
Site Created By: libMesh Developers
Last modified: February 05 2013 19:54:48 UTC
Hosted By: