/*! \brief Improves the quality of the MeshSet, calling some methods specified in a class derived from VertexMover \param const MeshSet &: this MeshSet is looped over. Only the mutable data members are changed (such as currentVertexInd). */ double VertexMover::loop_over_mesh( Mesh* mesh, MeshDomain* domain, const Settings* settings, MsqError& err ) { // Get the patch data to use for the first iteration OFEvaluator& obj_func = get_objective_function_evaluator(); PatchData patch; patch.set_mesh( mesh ); patch.set_domain( domain ); if (settings) patch.attach_settings( settings ); bool one_patch = false, did_some, all_culled; std::vector<Mesh::VertexHandle> patch_vertices; std::vector<Mesh::ElementHandle> patch_elements; PatchSet* patch_set = get_patch_set(); if (!patch_set) { MSQ_SETERR(err)("No PatchSet for QualityImprover!", MsqError::INVALID_STATE); return 0.0; } patch_set->set_mesh( mesh ); std::vector<PatchSet::PatchHandle> patch_list; patch_set->get_patch_handles( patch_list, err ); MSQ_ERRZERO(err); // Get termination criteria TerminationCriterion* outer_crit=this->get_outer_termination_criterion(); TerminationCriterion* inner_crit=this->get_inner_termination_criterion(); if(outer_crit == 0){ MSQ_SETERR(err)("Termination Criterion pointer is Null", MsqError::INVALID_STATE); return 0.; } if(inner_crit == 0){ MSQ_SETERR(err)("Termination Criterion pointer for inner loop is Null", MsqError::INVALID_STATE); return 0.; } // If using a local patch, suppress output of inner termination criterion if (patch_list.size() > 1) inner_crit->set_debug_output_level(3); else one_patch = true; // Initialize outer loop this->initialize(patch, err); if (MSQ_CHKERR(err)) goto ERROR; obj_func.initialize( mesh, domain, settings, patch_set, err ); if (MSQ_CHKERR(err)) goto ERROR; outer_crit->reset_outer(mesh, domain, obj_func, settings, err); if (MSQ_CHKERR(err)) goto ERROR; // if only one patch, get the patch now if (one_patch) { patch_set->get_patch( patch_list[0], patch_elements, patch_vertices, err ); if (MSQ_CHKERR(err)) goto ERROR; patch.set_mesh_entities( patch_elements, patch_vertices, err ); if (MSQ_CHKERR(err)) goto ERROR; } // Loop until outer termination criterion is met did_some = true; while (!outer_crit->terminate()) { if (!did_some) { MSQ_SETERR(err)("Inner termiation criterion satisfied for all patches " "without meeting outer termination criterion. This is " "an infinite loop. Aborting.", MsqError::INVALID_STATE); break; } did_some = false; all_culled = true; // Loop over each patch std::vector<PatchSet::PatchHandle>::iterator p_iter = patch_list.begin(); while( p_iter != patch_list.end() ) { if (!one_patch) { // if only one patch (global) re-use the previous one // loop until we get a non-empty patch. patch will be empty // for culled vertices with element-on-vertex patches do { patch_set->get_patch( *p_iter, patch_elements, patch_vertices, err ); if (MSQ_CHKERR(err)) goto ERROR; ++p_iter; } while (patch_elements.empty() && p_iter != patch_list.end()) ; if (patch_elements.empty()) { // no more non-culled vertices break; } all_culled = false; patch.set_mesh_entities( patch_elements, patch_vertices, err ); if (MSQ_CHKERR(err)) goto ERROR; } else { ++p_iter; all_culled = false; } // Initialize for inner iteration this->initialize_mesh_iteration(patch, err); if (MSQ_CHKERR(err)) goto ERROR; obj_func.reset(); outer_crit->reset_patch( patch, err ); if (MSQ_CHKERR(err)) goto ERROR; inner_crit->reset_inner( patch, obj_func, err ); if (MSQ_CHKERR(err)) goto ERROR; inner_crit->reset_patch( patch, err ); if (MSQ_CHKERR(err)) goto ERROR; // Don't even call optimizer if inner termination // criterion has already been met. if (!inner_crit->terminate()) { did_some = true; // Call optimizer - should loop on inner_crit->terminate() this->optimize_vertex_positions( patch, err ); if (MSQ_CHKERR(err)) goto ERROR; // Update for changes during inner iteration // (during optimizer loop) outer_crit->accumulate_patch( patch, err ); if (MSQ_CHKERR(err)) goto ERROR; inner_crit->cull_vertices( patch, obj_func, err ); if (MSQ_CHKERR(err)) goto ERROR; patch.update_mesh( err ); if (MSQ_CHKERR(err)) goto ERROR; } } this->terminate_mesh_iteration(patch, err); if (MSQ_CHKERR(err)) goto ERROR; outer_crit->accumulate_outer( mesh, domain, obj_func, settings, err ); if (MSQ_CHKERR(err)) goto ERROR; if (all_culled) break; } ERROR: //call the criteria's cleanup funtions. outer_crit->cleanup(mesh,domain,err); inner_crit->cleanup(mesh,domain,err); //call the optimization cleanup function. this->cleanup(); return 0.; }
/*! \brief Improves the quality of the MeshSet, calling some methods specified in a class derived from VertexMover \param const MeshSet &: this MeshSet is looped over. Only the mutable data members are changed (such as currentVertexInd). */ double VertexMover::loop_over_mesh( ParallelMesh* mesh, MeshDomain* domain, const Settings* settings, MsqError& err ) { std::vector<size_t> junk; Mesh::VertexHandle vertex_handle; // Get the patch data to use for the first iteration OFEvaluator& obj_func = get_objective_function_evaluator(); PatchData patch; patch.set_mesh( (Mesh*) mesh ); patch.set_domain( domain ); patch.attach_settings( settings ); ParallelHelper* helper = mesh->get_parallel_helper(); if (!helper) { MSQ_SETERR(err)("No ParallelHelper instance", MsqError::INVALID_STATE); return 0; } helper->smoothing_init(err); MSQ_ERRZERO(err); bool did_some, all_culled; std::vector<Mesh::VertexHandle> patch_vertices; std::vector<Mesh::ElementHandle> patch_elements; std::vector<Mesh::VertexHandle> fixed_vertices; std::vector<Mesh::VertexHandle> free_vertices; // Get termination criteria TerminationCriterion* outer_crit=this->get_outer_termination_criterion(); TerminationCriterion* inner_crit=this->get_inner_termination_criterion(); if(outer_crit == 0){ MSQ_SETERR(err)("Termination Criterion pointer is Null", MsqError::INVALID_STATE); return 0.; } if(inner_crit == 0){ MSQ_SETERR(err)("Termination Criterion pointer for inner loop is Null", MsqError::INVALID_STATE); return 0.; } PatchSet* patch_set = get_patch_set(); if (!patch_set) { MSQ_SETERR(err)("No PatchSet for QualityImprover!", MsqError::INVALID_STATE); return 0.0; } patch_set->set_mesh( (Mesh*)mesh ); std::vector<PatchSet::PatchHandle> patch_list; patch_set->get_patch_handles( patch_list, err ); MSQ_ERRZERO(err); // Initialize outer loop this->initialize(patch, err); if (MSQ_CHKERR(err)) goto ERROR; obj_func.initialize( (Mesh*)mesh, domain, settings, patch_set, err ); if (MSQ_CHKERR(err)) goto ERROR; outer_crit->reset_outer( (Mesh*)mesh, domain, obj_func, settings, err); if (MSQ_CHKERR(err)) goto ERROR; // Loop until outer termination criterion is met did_some = true; while (!outer_crit->terminate()) { if (!did_some) { MSQ_SETERR(err)("Inner termiation criterion satisfied for all patches " "without meeting outer termination criterion. This is " "an infinite loop. Aborting.", MsqError::INVALID_STATE); break; } did_some = false; all_culled = true; ///*** smooth the interior ***//// // get the fixed vertices (i.e. the ones *not* part of the first independent set) helper->compute_first_independent_set(fixed_vertices); // sort the fixed vertices std::sort(fixed_vertices.begin(), fixed_vertices.end()); // Loop over each patch std::vector<PatchSet::PatchHandle>::iterator p_iter = patch_list.begin(); while( p_iter != patch_list.end() ) { // loop until we get a non-empty patch. patch will be empty // for culled vertices with element-on-vertex patches do { patch_set->get_patch( *p_iter, patch_elements, patch_vertices, err ); if (MSQ_CHKERR(err)) goto ERROR; ++p_iter; } while (patch_elements.empty() && p_iter != patch_list.end()) ; if (patch_elements.empty()) { // no more non-culled vertices break; } if (patch_vertices.empty()) // global patch hack (means all mesh vertices) { mesh->get_all_vertices(patch_vertices, err); } free_vertices.clear(); for (size_t i = 0; i < patch_vertices.size(); ++i) if (!std::binary_search(fixed_vertices.begin(), fixed_vertices.end(), patch_vertices[i])) free_vertices.push_back(patch_vertices[i]); if (free_vertices.empty()) { // all vertices were fixed -> skip patch continue; } all_culled = false; patch.set_mesh_entities( patch_elements, free_vertices, err ); if (MSQ_CHKERR(err)) goto ERROR; // Initialize for inner iteration this->initialize_mesh_iteration(patch, err); if (MSQ_CHKERR(err)) goto ERROR; obj_func.reset(); outer_crit->reset_patch( patch, err ); if (MSQ_CHKERR(err)) goto ERROR; inner_crit->reset_inner( patch, obj_func, err ); if (MSQ_CHKERR(err)) goto ERROR; inner_crit->reset_patch( patch, err ); if (MSQ_CHKERR(err)) goto ERROR; // Don't even call optimizer if inner termination // criterion has already been met. if (!inner_crit->terminate()) { did_some = true; // Call optimizer - should loop on inner_crit->terminate() this->optimize_vertex_positions( patch, err ); if (MSQ_CHKERR(err)) goto ERROR; // Update for changes during inner iteration // (during optimizer loop) outer_crit->accumulate_patch( patch, err ); if (MSQ_CHKERR(err)) goto ERROR; inner_crit->cull_vertices( patch, obj_func, err ); if (MSQ_CHKERR(err)) goto ERROR; patch.update_mesh( err ); if (MSQ_CHKERR(err)) goto ERROR; } } helper->communicate_first_independent_set(err); if (MSQ_CHKERR(err)) goto ERROR; ///*** smooth the boundary ***//// while (helper->compute_next_independent_set()) { // Loop over all boundary elements while(helper->get_next_partition_boundary_vertex(vertex_handle)) { patch_vertices.clear(); patch_vertices.push_back(vertex_handle); patch_elements.clear(); mesh->vertices_get_attached_elements( &vertex_handle, 1, patch_elements, junk, err ); all_culled = false; patch.set_mesh_entities( patch_elements, patch_vertices, err ); if (MSQ_CHKERR(err)) goto ERROR; // Initialize for inner iteration this->initialize_mesh_iteration(patch, err); if (MSQ_CHKERR(err)) goto ERROR; obj_func.reset(); outer_crit->reset_patch( patch, err ); if (MSQ_CHKERR(err)) goto ERROR; inner_crit->reset_inner( patch, obj_func, err ); if (MSQ_CHKERR(err)) goto ERROR; inner_crit->reset_patch( patch, err ); if (MSQ_CHKERR(err)) goto ERROR; // Don't even call optimizer if inner termination // criterion has already been met. if (!inner_crit->terminate()) { did_some = true; // Call optimizer - should loop on inner_crit->terminate() this->optimize_vertex_positions( patch, err ); if (MSQ_CHKERR(err)) goto ERROR; // Update for changes during inner iteration // (during optimizer loop) outer_crit->accumulate_patch( patch, err ); if (MSQ_CHKERR(err)) goto ERROR; inner_crit->cull_vertices( patch, obj_func, err ); if (MSQ_CHKERR(err)) goto ERROR; patch.update_mesh( err ); if (MSQ_CHKERR(err)) goto ERROR; } } helper->communicate_next_independent_set(err); if (MSQ_CHKERR(err)) goto ERROR; } this->terminate_mesh_iteration(patch, err); if (MSQ_CHKERR(err)) goto ERROR; outer_crit->accumulate_outer( mesh, domain, obj_func, settings, err ); if (MSQ_CHKERR(err)) goto ERROR; if (all_culled) break; } ERROR: //call the criteria's cleanup funtions. outer_crit->cleanup(mesh,domain,err); MSQ_CHKERR(err); inner_crit->cleanup(mesh,domain,err); MSQ_CHKERR(err); //call the optimization cleanup function. this->cleanup(); // close the helper helper->smoothing_close(err); MSQ_CHKERR(err); return 0.; }
time_t read_cache() { FILE * fp; char buff[BUFSIZ]; int state = CACHE_NEED_FILE; CvsFile * f = NULL; PatchSet * ps = NULL; char datebuff[20] = ""; char authbuff[AUTH_STR_MAX] = ""; char tagbuff[LOG_STR_MAX] = ""; int tag_flags = 0; char branchbuff[LOG_STR_MAX] = ""; int branch_add = 0; int logbufflen = LOG_STR_MAX + 1; char * logbuff = malloc(logbufflen); time_t cache_date = -1; int read_version; if (logbuff == NULL) { debug(DEBUG_SYSERROR, "could not malloc %d bytes for logbuff in read_cache", logbufflen); exit(1); } logbuff[0] = 0; if (!(fp = cache_open("r"))) goto out; /* first line is cache version format "cache version: %d\n" */ if (!fgets(buff, BUFSIZ, fp) || strncmp(buff, "cache version:", 14)) { debug(DEBUG_APPERROR, "bad cvsps.cache file"); goto out_close; } if ((read_version = atoi(buff + 15)) != cache_version) { debug(DEBUG_APPERROR, "bad cvsps.cache version %d, expecting %d. ignoring cache", read_version, cache_version); goto out_close; } /* second line is date cache was created, format "cache date: %d\n" */ if (!fgets(buff, BUFSIZ, fp) || strncmp(buff, "cache date:", 11)) { debug(DEBUG_APPERROR, "bad cvsps.cache file"); goto out_close; } cache_date = atoi(buff + 12); debug(DEBUG_STATUS, "read cache_date %d", (int)cache_date); while (fgets(buff, BUFSIZ, fp)) { int len = strlen(buff); switch(state) { case CACHE_NEED_FILE: if (strncmp(buff, "file:", 5) == 0) { len -= 6; f = create_cvsfile(); f->filename = xstrdup(buff + 6); f->filename[len-1] = 0; /* Remove the \n at the end of line */ debug(DEBUG_STATUS, "read cache filename '%s'", f->filename); put_hash_object_ex(file_hash, f->filename, f, HT_NO_KEYCOPY, NULL, NULL); state = CACHE_NEED_BRANCHES; } else { state = CACHE_NEED_PS; } break; case CACHE_NEED_BRANCHES: if (buff[0] != '\n') { char * tag; tag = strchr(buff, ':'); if (tag) { *tag = 0; tag += 2; buff[len - 1] = 0; cvs_file_add_branch(f, buff, tag); } } else { f->have_branches = 1; state = CACHE_NEED_SYMBOLS; } break; case CACHE_NEED_SYMBOLS: if (buff[0] != '\n') { char * rev; rev = strchr(buff, ':'); if (rev) { *rev = 0; rev += 2; buff[len - 1] = 0; cvs_file_add_symbol(f, rev, buff); } } else { state = CACHE_NEED_REV; } break; case CACHE_NEED_REV: if (isdigit(buff[0])) { char * p = strchr(buff, ' '); if (p) { CvsFileRevision * rev; *p++ = 0; buff[len-1] = 0; rev = cvs_file_add_revision(f, buff); if (strcmp(rev->branch, p) != 0) { debug(DEBUG_APPERROR, "branch mismatch for %s:%s %s != %s", rev->file->filename, rev->rev, rev->branch, p); } } } else { state = CACHE_NEED_FILE; } break; case CACHE_NEED_PS: if (strncmp(buff, "patchset:", 9) == 0) state = CACHE_NEED_PS_DATE; break; case CACHE_NEED_PS_DATE: if (strncmp(buff, "date:", 5) == 0) { /* remove prefix "date: " and LF from len */ len -= 6; strzncpy(datebuff, buff + 6, MIN(len, sizeof(datebuff))); state = CACHE_NEED_PS_AUTHOR; } break; case CACHE_NEED_PS_AUTHOR: if (strncmp(buff, "author:", 7) == 0) { /* remove prefix "author: " and LF from len */ len -= 8; strzncpy(authbuff, buff + 8, MIN(len, AUTH_STR_MAX)); state = CACHE_NEED_PS_TAG; } break; case CACHE_NEED_PS_TAG: if (strncmp(buff, "tag:", 4) == 0) { /* remove prefix "tag: " and LF from len */ len -= 5; strzncpy(tagbuff, buff + 5, MIN(len, LOG_STR_MAX)); state = CACHE_NEED_PS_TAG_FLAGS; } break; case CACHE_NEED_PS_TAG_FLAGS: if (strncmp(buff, "tag_flags:", 10) == 0) { /* remove prefix "tag_flags: " and LF from len */ len -= 11; tag_flags = atoi(buff + 11); state = CACHE_NEED_PS_BRANCH; } break; case CACHE_NEED_PS_BRANCH: if (strncmp(buff, "branch:", 7) == 0) { /* remove prefix "branch: " and LF from len */ len -= 8; strzncpy(branchbuff, buff + 8, MIN(len, LOG_STR_MAX)); state = CACHE_NEED_PS_BRANCH_ADD; } break; case CACHE_NEED_PS_BRANCH_ADD: if (strncmp(buff, "branch_add:", 11) == 0) { /* remove prefix "branch_add: " and LF from len */ len -= 12; branch_add = atoi(buff + 12); state = CACHE_NEED_PS_DESCR; } break; case CACHE_NEED_PS_DESCR: if (strncmp(buff, "descr:", 6) == 0) state = CACHE_NEED_PS_EOD; break; case CACHE_NEED_PS_EOD: if (strcmp(buff, CACHE_DESCR_BOUNDARY) == 0) { debug(DEBUG_STATUS, "patch set %s %s %s %s", datebuff, authbuff, logbuff, branchbuff); ps = get_patch_set(datebuff, logbuff, authbuff, branchbuff, NULL); /* the tag and tag_flags will be assigned by the resolve_global_symbols code * ps->tag = (strlen(tagbuff)) ? get_string(tagbuff) : NULL; * ps->tag_flags = tag_flags; */ ps->branch_add = branch_add; state = CACHE_NEED_PS_MEMBERS; } else { /* Make sure we have enough in the buffer */ int len = strlen(buff); if (strlen(logbuff) + len >= LOG_STR_MAX) { logbufflen += (len >= LOG_STR_MAX ? (len+1) : LOG_STR_MAX); char * newlogbuff = realloc(logbuff, logbufflen); if (newlogbuff == NULL) { debug(DEBUG_SYSERROR, "could not realloc %d bytes for logbuff in read_cache", logbufflen); exit(1); } logbuff = newlogbuff; } strcat(logbuff, buff); } break; case CACHE_NEED_PS_MEMBERS: if (strncmp(buff, "members:", 8) == 0) state = CACHE_NEED_PS_EOM; break; case CACHE_NEED_PS_EOM: if (buff[0] == '\n') { datebuff[0] = 0; authbuff[0] = 0; tagbuff[0] = 0; tag_flags = 0; branchbuff[0] = 0; branch_add = 0; logbuff[0] = 0; state = CACHE_NEED_PS; } else { PatchSetMember * psm = create_patch_set_member(); parse_cache_revision(psm, buff); patch_set_add_member(ps, psm); } break; } } out_close: fclose(fp); out: free(logbuff); return cache_date; }