Esempio n. 1
0
int
main(int argc, char *argv[])
{
    const char *fn = "cube.dat";
    ELEMENT *e;
    GRID *g;
    DOF *u;
    int i, n;

    /* Test initialize MPI before phgInit */
    MPI_Init(&argc, &argv);

    phgInit(&argc, &argv);

    g = phgNewGrid(-1);
    if (argc > 1)
	fn = argv[1];
    if (!phgImport(g, fn, FALSE))
	phgError(1, "can't read file \"%s\".\n", fn);
    phgRefineAllElements(g, 0);

    u = phgDofNew(g, DOF_DEFAULT, 1, "u", DofNoAction);
    n = u->type->nbas;
    ForAllElements(g, e) {
	FLOAT xyz[3];
	const FLOAT *c;
	for (i = 0; i < n; i++) {
	    c = phgDofGetElementCoordinates(u, e, i);
	    phgDofGetElementBasisInfo_(u, e, i, NULL, NULL, NULL, xyz, NULL);
	    assert(!memcmp(c, xyz, sizeof(xyz)));
	}
    }
Esempio n. 2
0
/*
 *  Moving mesh initialization, following jobs are done:
 *  1. create interior vertex map and boundary vertex map,
 *  2. create a logical mesh.
 *  */
MovingMesh *
phgMovingMeshCreate(GRID *g, PARAMS *params)
{
    MovingMesh *mmesh;
    INT i, k;
    FLOAT *v;
    
    _m = phgCalloc(1, sizeof(*_m));
    _m->params = params;
    _m->g = g;

    _m->logical_node = 
	phgDofNew(g, DOF_P1, 3, "logical node coordinates", DofNoAction);
    _m->logical_node->DB_mask[0] = MM_CONSTR0;
    _m->logical_node->DB_mask[1] = MM_CONSTR1;
    _m->logical_node->DB_mask[2] = MM_CONSTR2;

    _m->logical_move = 
	phgDofNew(g, DOF_P1, 3, "logical move direction", DofNoAction);
    _m->move = 
	phgDofNew(g, DOF_P1, 3, "node move direction", DofNoAction);
    _m->monitor = 
	phgDofNew(g, DOF_P0, 1, "monitor", DofNoAction);

    /* P1 bases */
    _m->phi = 
	phgDofNew(g, DOF_P1, 1, "P1 bases", DofNoAction);
    _m->phi->DB_mask[0] = 0;
    _m->map = phgMapCreate(_m->phi, NULL);

    /* Boundary types of verties */
    getBdryTypes(_m);

    /* get logical mesh
     * Note: here logical mesh is identical to original mesh*/
    v = _m->logical_node->data;
    for (i = 0; i < g->nvert; i++) {
	if (!(g->types_vert[i] == UNREFERENCED)) {
	    for (k = 0; k < Dim; k++)
		v[i*Dim + k] = g->verts[i][k];
	}
    } /* Point loop: local */
    DOF_SCALE(_m->logical_node);

    return _m;
}
Esempio n. 3
0
int
main(int argc, char *argv[])
{
    GRID *g;
    MAP *map, *map0;
    INT n = 4;
    DOF *u;
    static INT pre_refines = 0;
    static char *fn = "../test/cube.dat";
    /*static char *fn = "../albert-files/cube5.dat";*/

    phgOptionsPreset("-dof_type P1");
    phgOptionsRegisterInt("-pre_refines", "Pre-refinements", &pre_refines);
    phgInit(&argc, &argv);
    g = phgNewGrid(-1);
    if (!phgImport(g, fn, FALSE))
	phgError(1, "can't read file \"%s\".\n", fn);
    phgRefineAllElements(g, pre_refines);
    phgPartitionGrid(g);

    u = phgDofNew(g, DOF_DEFAULT, 1, "u", DofNoAction);
    map0 = phgMapCreate(u, NULL);

    phgInfo(-1, "\n");
    phgInfo(-1, "Test special map with size = 0 on all but one process:\n");
    map = phgMapCreateSimpleMap(g->comm, g->rank == g->nprocs - 1 ? n : 0, n);
    phgInfo(-1, "---- DOF rows, special columns:\n");
    do_test(map0, map);
    phgInfo(-1, "---- Special rows, DOF columns:\n");
    do_test(map, map0);
    phgInfo(-1, "---- Special rows, special columns:\n");
    do_test(map, map);
    phgMapDestroy(&map);

    phgInfo(-1, "\n");
    phgInfo(-1, "Test serial map:\n");
    map = phgMapCreateSimpleMap(g->comm, n, n);
    phgInfo(-1, "---- DOF rows, serial columns:\n");
    do_test(map0, map);
    phgInfo(-1, "---- serial rows, DOF columns:\n");
    do_test(map, map0);
    phgInfo(-1, "---- Serial rows, serial columns:\n");
    do_test(map, map);
    phgMapDestroy(&map);

    phgMapDestroy(&map0);
    phgDofFree(&u);
    phgFreeGrid(&g);
    phgFinalize();

    return 0;
}
Esempio n. 4
0
DOF *
phgDofCopy_(DOF *src, DOF **dest_ptr, DOF_TYPE *newtype,
	    const char *name, const char *srcfile, int srcline)
/* returns a new DOF whose type is 'newtype', and whose values are evaluated
 * using 'src' (a copy of src). */
{
    GRID *g = src->g;
    SIMPLEX *e;
    FLOAT w = 1.0, *basvalues = NULL, *a, *d, *buffer = NULL;
    int i, k, dim, dim_new, count = 0, nvalues, nd;
    INT n;
    DOF *wgts = NULL;
    DOF *dest = (dest_ptr == NULL ? NULL : *dest_ptr);
    BYTE *flags0, *flags;
    char *auto_name;
    DOF_TYPE *oldtype;
    BOOLEAN basflag = FALSE;

    MagicCheck(DOF, dest)

    if (dest != NULL && newtype != NULL && dest->type != newtype) {
	phgDofFree(&dest);
	dest = NULL;
    }

    dim = DofDim(src);
    /* the name of dest */
    if ((auto_name = (void *)name) == NULL) {
#if 0
	auto_name = phgAlloc(strlen(src->name) + 8 + 1);
	sprintf(auto_name, "copy of %s", src->name);
#else
	auto_name = strdup(src->name);
#endif
    }

    if (dest == NULL) {
	if (newtype == NULL)
	    newtype = src->type;
	dim_new = (newtype == NULL ? DofTypeDim(src) : newtype->dim);
	assert(dim % dim_new == 0);
	dest = phgDofNew_(g, newtype, newtype == NULL ? src->hp : NULL,
			  dim / dim_new, auto_name, DofNoAction,
			  srcfile, srcline);
	if (dest_ptr != NULL)
	    *dest_ptr = dest;
    }
    else {
	assert(dim == DofDim(dest));
	phgFree(dest->name); dest->name = strdup(auto_name);
	dest->srcfile = srcfile;
	dest->srcline = srcline;
	phgFree(dest->cache_func); dest->cache_func = NULL;
	newtype = dest->type;
	if (!SpecialDofType(newtype))
	    memset(dest->data, 0, DofGetDataCount(dest) * sizeof(*dest->data));
    }
    if (auto_name != name)
	phgFree(auto_name);

    phgDofClearCache(NULL, dest, NULL, NULL, FALSE);

    dest->DB_mask = src->DB_mask;
    if (src->DB_masks != NULL) {
	if (dest->DB_masks == NULL)
	    dest->DB_masks = phgAlloc(dest->dim * sizeof(*dest->DB_masks));
	memcpy(dest->DB_masks, src->DB_masks, dest->dim * sizeof(*dest->DB_masks));
    }
    dest->invariant = src->invariant;

    if (SpecialDofType(newtype)) {
	assert(newtype == src->type);
	dest->userfunc = src->userfunc;
	dest->userfunc_lambda = src->userfunc_lambda;
	if (newtype == DOF_CONSTANT)
	    memcpy(dest->data, src->data, dim * sizeof(*dest->data));
	return dest;
    }

    if ((newtype != NULL && newtype == src->type) ||
	(newtype == NULL && src->hp == dest->hp)) {
	/* simply duplicate the data */
	size_t size = DofGetDataCount(dest);
	if (size > 0)
	    memcpy(dest->data, src->data, sizeof(FLOAT) * size);
	dest->userfunc = src->userfunc;
	dest->userfunc_lambda = src->userfunc_lambda;
	return dest;
    }

    if (src->type == DOF_ANALYTIC) {
	if (src->userfunc_lambda != NULL)
	    phgDofSetDataByLambdaFunction(dest, src->userfunc_lambda);
	else
	    phgDofSetDataByFunction(dest, src->userfunc);
	return dest;
    }

    if (newtype != NULL && newtype->BasFuncs == NULL)
	phgError(1, "phgDofCopy: basis funcs for DOF type \"%s\" undefined.\n",
		 newtype->name);

    dest->userfunc = src->userfunc;
    dest->userfunc_lambda = src->userfunc_lambda;

    oldtype = src->type;
    if (oldtype == NULL)
	oldtype = src->hp->info->types[src->hp->info->min_order];

    if (!SpecialDofType(oldtype) && newtype != NULL && newtype->points != NULL
	&& !DofIsHP(src)) {
	basflag = TRUE;
	count = oldtype->nbas * oldtype->dim;
	basvalues = phgAlloc(newtype->nbas * count * sizeof(*basvalues));

	if (oldtype->invariant == TRUE)
	    get_bas_funcs(src, dest, src->g->roots, basvalues);
    }

    if (newtype == NULL)
	newtype = dest->hp->info->types[dest->hp->max_order];

    flags0 = phgCalloc((newtype->np_vert > 0 ? g->nvert : 0)
		       + (newtype->np_edge > 0 ? g->nedge : 0)
		       + (newtype->np_face > 0 ? g->nface : 0),
		       sizeof(*flags0));

    if (!SpecialDofType(oldtype) && oldtype->continuity < 0) {
	static DOF_TYPE DOF_WGTS = {DofCache,
	    "Weights", NULL, NULL, NULL, NULL, NULL, NULL, NULL,
	    phgDofInitFuncPoint, NULL, NULL, NULL, FE_None,
	    FALSE, FALSE, -1, 0, 0, -1, 1, 0, 0, 0, 0
	};
	DOF_WGTS.np_vert = (newtype->np_vert > 0) ? 1 : 0;
	DOF_WGTS.np_edge = (newtype->np_edge > 0) ? 1 : 0;
	DOF_WGTS.np_face = (newtype->np_face > 0) ? 1 : 0;
	DOF_WGTS.nbas = DOF_WGTS.np_vert * NVert + DOF_WGTS.np_edge * NEdge +
	    DOF_WGTS.np_face * NFace;
	if (DOF_WGTS.nbas > 0) {
	    /* Other cases will be implemented later when really needed */
	    wgts = phgDofNew(g, &DOF_WGTS, 1, "weights", DofNoAction);
	    phgDofSetDataByValue(wgts, 0.0);
	    phgDofSetDataByValue(dest, 0.0);
	    /* allocate buffer for storing weighted vertex/edge/face data */
	    if ((n = DofGetDataCount(dest) - DofGetElementDataCount(dest)) > 0)
		buffer = phgCalloc(n, sizeof(*buffer));
	}
    }

    nvalues = dest->dim;
    cache_dof = src;
    bas_count = count;
    ForAllElements(g, e) {
	if (wgts != NULL) {
#if 0
	    /* use element volume as weight */
	    w = phgGeomGetVolume(g, e);
#else
	    /* use 1 as weight */
	    w = 1.0;
#endif
	}

	if (basflag && oldtype->invariant == FALSE)
	    get_bas_funcs(src, dest, e, basvalues);
	bas = basvalues;
	flags = flags0;

	if (DofIsHP(dest))
	    newtype = dest->hp->info->types[dest->hp->elem_order[e->index]];

	if (newtype->np_vert > 0) {
	    nd = nvalues * newtype->np_vert;
	    for (k = 0; k < NVert; k++) {
		if (flags[n = e->verts[k]] && wgts == NULL) {
		    /* note: count==0 and bas==NULL for variable order DOF */
		    bas += count * newtype->np_vert;
		    continue;
		}
		flags[n] = TRUE;
		a = DofVertexData(dest, n);
		newtype->InitFunc(dest, e, VERTEX, k, NULL, func, NULL, a,
					NULL);
		if (wgts != NULL) {
		    d = buffer + (a - DofData(dest));
		    for (i = 0; i < nd; i++)
			*(d++) += *(a++) * w;
		    *DofVertexData(wgts, n) += w;
		}
	    }
	    flags += g->nvert;
	}

	if (newtype->np_edge > 0) {
	    nd = nvalues * newtype->np_edge;
	    for (k = 0; k < NEdge; k++) {
		if (flags[n = e->edges[k]] && wgts == NULL) {
		    /* note: count==0 and bas==NULL for variable order DOF */
		    bas += count * newtype->np_edge;
		    continue;
		}
		flags[n] = TRUE;
		a = DofEdgeData(dest, n);
		newtype->InitFunc(dest, e, EDGE, k, NULL, func, NULL, a,
					NULL);
		if (wgts != NULL) {
		    d = buffer + (a - DofData(dest));
		    if (DofIsHP(dest))
			nd = dest->dim * (dest->hp->edge_index[n + 1] -
					  dest->hp->edge_index[n]);
		    for (i = 0; i < nd; i++)
			*(d++) += *(a++) * w;
		    *DofEdgeData(wgts, n) += w;
		}
	    }
	    flags += g->nedge;
	}

	if (newtype->np_face > 0) {
	    nd = nvalues * newtype->np_face;
	    for (k = 0; k < NFace; k++) {
		if (flags[n = e->faces[k]] && wgts == NULL) {
		    /* note: count==0 and bas==NULL for variable order DOF */
		    bas += count * newtype->np_face;
		    continue;
		}
		flags[n] = TRUE;
		a = DofFaceData(dest, n);
		newtype->InitFunc(dest, e, FACE, k, NULL, func, NULL, a,
					NULL);
		if (wgts != NULL) {
		    d = buffer + (a - DofData(dest));
		    if (DofIsHP(dest))
			nd = dest->dim * (dest->hp->face_index[n + 1] -
						 dest->hp->face_index[n]);
		    for (i = 0; i < nd; i++)
			*(d++) += *(a++) * w;
		    *DofFaceData(wgts, n) += w;
		}
	    }
	}

	if (newtype->np_elem > 0) {
	    a = DofElementData(dest, e->index);
	    newtype->InitFunc(dest, e, ELEMENT, 0, NULL, func, NULL, a,
					NULL);
	}
    }

    phgFree(basvalues);
    phgFree(flags0);

    if (wgts == NULL)
	return dest;

    if ((n = DofGetDataCount(dest) - DofGetElementDataCount(dest)) > 0) {
	memcpy(DofData(dest), buffer, n * sizeof(*buffer));
	phgFree(buffer);
    }

    if (DofIsHP(dest))
	newtype = dest->hp->info->types[dest->hp->max_order];

    a = DofData(dest);
    d = DofData(wgts);

#if USE_MPI
    /* FIXME: directly interacting with the vector assembly code in solver.c
       is more efficient */
    if (g->nprocs > 1) {
	SOLVER *solver = phgSolverCreate(SOLVER_BUILTIN, dest, NULL);
	INT K = 0, I;
	int j;

	if (newtype->np_vert > 0) {
	    nd = dest->count_vert;
	    for (n = 0; n < g->nvert; n++, d++) {
		if (g->types_vert[n] == UNREFERENCED) {
		    K += nd;
		    a += nd;
		    continue;
		}
		for (j = 0; j < nd; j++, K++, a++) {
		    I = phgSolverMapD2L(solver, 0, K);
		    assert(I >= 0 && I < solver->mat->rmap->localsize);
		    phgSolverAddRHSEntry(solver, I, *a);
		    phgSolverAddMatrixEntry(solver, I, I, *d);
		}
	    }
	}

	if (newtype->np_edge > 0) {
	    nd = nvalues * newtype->np_edge;
	    for (n = 0; n < g->nedge; n++, d++) {
		if (DofIsHP(dest))
		    nd = dest->dim * (dest->hp->edge_index[n + 1] -
					     dest->hp->edge_index[n]);
		if (g->types_edge[n] == UNREFERENCED) {
		    K += nd;
		    a += nd;
		    continue;
		}
		for (j = 0; j < nd; j++, K++, a++) {
		    I = phgSolverMapD2L(solver, 0, K);
		    assert(I >= 0 && I < solver->mat->rmap->localsize);
		    phgSolverAddRHSEntry(solver, I, *a);
		    phgSolverAddMatrixEntry(solver, I, I, *d);
		}
	    }
	}

	if (newtype->np_face > 0) {
	    nd = nvalues * newtype->np_face;
	    for (n = 0; n < g->nface; n++, d++) {
		if (DofIsHP(dest))
		    nd = dest->dim * (dest->hp->face_index[n + 1] -
					     dest->hp->face_index[n]);
		if (g->types_face[n] == UNREFERENCED) {
		    K += nd;
		    a += nd;
		    continue;
		}
		for (j = 0; j < nd; j++, K++, a++) {
		    I = phgSolverMapD2L(solver, 0, K);
		    assert(I >= 0 && I < solver->mat->rmap->localsize);
		    phgSolverAddRHSEntry(solver, I, *a);
		    phgSolverAddMatrixEntry(solver, I, I, *d);
		}
	    }
	}

	if (newtype->np_elem > 0) {
	    nd = nvalues * newtype->np_elem;
	    for (n = 0; n < g->nelem; n++) {
		if (DofIsHP(dest))
		    nd = dest->dim * (dest->hp->elem_index[n + 1] -
					     dest->hp->elem_index[n]);
		if (g->types_elem[n] == UNREFERENCED) {
		    K += nd;
		    a += nd;
		    continue;
		}
		for (j = 0; j < nd; j++, K++, a++) {
		    I = phgSolverMapD2L(solver, 0, K);
		    assert(I >= 0 && I < solver->mat->rmap->localsize);
		    phgSolverAddRHSEntry(solver, I, *a);
		    phgSolverAddMatrixEntry(solver, I, I, 1.0);
		}
	    }
	}

	phgSolverSolve(solver, TRUE, dest, NULL);
	phgSolverDestroy(&solver);

	phgDofFree(&wgts);

	return dest;
    }
#endif

    if (newtype->np_vert > 0) {
	k = nvalues * newtype->np_vert;
	for (n = 0; n < g->nvert; n++) {
	    if ((w = *(d++)) == 0.0) {
		a += k;
	    }
	    else if (k == 1) {
		*(a++) /= w;
	    }
	    else {
		w = 1.0 / w;
		for (i = 0; i < k; i++)
		    *(a++) *= w;
	    }
	}
    }

    if (newtype->np_edge > 0) {
	k = nvalues * newtype->np_edge;
	for (n = 0; n < g->nedge; n++) {
	    if (DofIsHP(dest))
		k = dest->dim * (dest->hp->edge_index[n + 1] -
					dest->hp->edge_index[n]);
	    if ((w = *(d++)) == 0.0) {
		a += k;
	    }
	    else if (k == 1) {
		*(a++) /= w;
	    }
	    else {
		w = 1.0 / w;
		for (i = 0; i < k; i++)
		    *(a++) *= w;
	    }
	}
    }

    if (newtype->np_face > 0) {
	k = nvalues * newtype->np_face;
	for (n = 0; n < g->nface; n++) {
	    if (DofIsHP(dest))
		k = dest->dim * (dest->hp->face_index[n + 1] -
					dest->hp->face_index[n]);
	    if ((w = *(d++)) == 0.0) {
		a += k;
	    }
	    else if (k == 1) {
		*(a++) /= w;
	    }
	    else {
		w = 1.0 / w;
		for (i = 0; i < k; i++)
		    *(a++) *= w;
	    }
	}
    }

    phgDofFree(&wgts);

    return dest;
}
Esempio n. 5
0
int
main(int argc, char *argv[])
{
    GRID *g;
    SIMPLEX *e;
    DOF **u, **p, **T, **gradu,
	*eu, *ep, *egradu, *ediv, *eT,
	*dH = NULL;
    FLOAT Time, *dt, res, non_du, non_dp, non_dT;
    INT tstep = 0, nelem;
    char mesh_file[100], hostname[256],
	data_file[100], data_u[100], data_p[100], data_T[100], data_Crd[100];
    size_t mem, mem_peak;
    int verb;
    double tt[3], tt1[3];
    /* ---------- NS ---------- */
    NSSolver *ns = NULL;
    SURF_BAS *surf_bas = NULL;
    LAYERED_MESH *gL = NULL;
    //GEO_INFO *geo = NULL;
    /* MG_BLOCK_DOFS *bk = NULL; */

    /* ================================================================================
     *
     *         Initialize Grid & parameters
     *
     * ================================================================================
     */
    /* Global (static) options */
    Unused(verb); 
     
    ns_params = phgParametersCreate();     
    
    phgInit(&argc, &argv);
    
    phgOptionsShowUsed();

    g = phgNewGrid(-1);
    //phgSetPeriodicity(g, ns_params->periodicity);
    phgImportSetBdryMapFunc(my_bc_map);
    if (ns_params->resume) {
	phgResumeStage(g, &Time, &tstep, mesh_file, data_file);
	phgPrintf("================================\n\n");
	phgPrintf("* RESUME from time:%E, tstep:%d\n", Time, tstep);
	phgPrintf("*             mesh:%s\n", mesh_file);
	phgPrintf("*             data:%s\n", data_file);
	phgPrintf("================================\n");

	if (!phgImport(g, mesh_file, FALSE))
	    phgError(1, "can't read file \"%s\".\n", ns_params->fn);

    }
    else {
	phgPrintf("Using mesh: %s\n", ns_params->fn);
	if (!phgImport(g, ns_params->fn, FALSE))
	    phgError(1, "can't read file \"%s\".\n", ns_params->fn);
    }
    checkBdry(g);
    elapsed_time(g, FALSE, 0.);	/* reset timer */
    gethostname(hostname, sizeof(hostname));
    printf("#%5d# runing PID %5d on %s \n", phgRank, getpid(), hostname);

    NsSolver_Options();
    phgPrintf("  Pre-refine & repartition ");
    phgRefineAllElements(g, ns_params->pre_refines);

    /* Set Reynolds number */
    Time = ns_params->time_start;	/* default: 0 */
    setFuncTime(Time);
    setFlowParameter(ns_params->Re, ns_params->nu, Time);
    


    /* ================================================================================
     *
     *         build ice grid
     *
     * ================================================================================
     */

    iceInit(g, &gL);
    phgPrintf("Geometry initialization done!\n");
    phgExportVTK(g, "ice_domain.vtk", NULL, NULL);


    /* ================================================================================
     *
     *         Create INS solver
     *
     * ================================================================================
     */

    /* Note: pointers u, p, gradu, dt
     *       DIRECTLY access private member of INS solver.
     */
     
    phgPrintf("  Create INS solver");
    tstep = 1;			/* time step start at 1 */
    setFuncTime(Time);          /* in file ins-bc.c: static */

    //data_sur_T = read_txt_data("./LAS_temp_for_mesh.txt");

    ns = phgNSCreate(g, ns_params);

    //get_mask_bot(ns);
    
    ns->time[1] = Time;
    u = ns->u; 
    p = ns->p;
    T = ns->T;
    gradu = ns->gradu;
    dH = ns->dH;
    dt = ns->dt;		/* direct accses ns  */
    dt[0] = ns_params->dt0;
    ns->gL = gL;
    //ns->bk = bk = NULL; //init_line_block(T[1], gL);   /* Use line block */
    elapsed_time(g, TRUE, phgPerfGetMflops(g, NULL, NULL));

    /* Init height & depth */
    if (gL != NULL){
	get_height_depth(ns);
    }

    /* surf bases */
    //surf_bas = ns->surf_bas;

#if 0
    DOF *beta = phgDofNew(g, DOF_P1, 1, "beta", func_beta);
    phgExportEnsight(g, "check", beta, NULL);
    phgFinalize();
    exit(1);
#endif



    /* ------------------------------------------------------------
     * 
     * Resume dof data.
     * 
     * ------------------------------------------------------------ */
    if (ns_params->resume) {
	FILE *fp = NULL;
	char fname[1000];
	phgResumeStage(g, &Time, &tstep, mesh_file, data_file);

	/* resume coord */
	{
	    const FLOAT *v = DofData(ns->coord);
	    int i, k;
	    //sprintf(data_Crd, OUTPUT_DIR "/ins_" NS_PROBLEM "_%05d.dat.Crd", tstep - 1);
	    sprintf(data_Crd, OUTPUT_DIR "/ins_" NS_PROBLEM "_%05d.dat.Crd", 2);
	    assert(ns->coord->type == DOF_P1);
	    load_dof_data3(g, ns->coord, data_Crd, mesh_file);
	    for (i = 0; i < g->nvert; i++) 
		for (k = 0; k < Dim; k++)
		    g->verts[i][k] = *(v++);
	    phgGeomInit_(g, TRUE);
	}

#if 1
	/* resmue u_{n-1} */
	//sprintf(data_file, OUTPUT_DIR "/ins_" NS_PROBLEM "_%05d.dat", tstep - 2);
	sprintf(data_file, OUTPUT_DIR "/ins_" NS_PROBLEM "_%05d.dat", 1);
	DATA_FILE_SURFIX;
	sprintf(fname, "%s.p%03d", data_u, g->rank);
	if ((fp = fopen(fname, "r")) == NULL) {
	    phgPrintf("*  u_{%d} unavailable.\n", tstep - 2);
	} 
	else {
	    fclose(fp);

	    phgDofCopy(u[1], &u[0], NULL, "u_{n}");
	    phgDofCopy(p[1], &p[0], NULL, "p_{n}");
	    phgDofCopy(T[1], &T[0], NULL, "T_{n}");
	    gradu[0] = NULL;

	    load_dof_data3(g, u[0], data_u, mesh_file);
	    load_dof_data3(g, p[0], data_p, mesh_file);
	    load_dof_data3(g, T[0], data_T, mesh_file);
	    phgPrintf("   Resume u_ {%5d}[%8d]:%24.12E p_ {%5d}[%8d]:%24.12E\n", 
		      tstep - 2, DofGetDataCountGlobal(u[0]), phgDofNormL2(u[0]), 
		      tstep - 2, DofGetDataCountGlobal(p[0]), phgDofNormL2(p[0]));
	    phgPrintf("   Resume T_{%5d}[%8d]:%24.12E\n", 
		      tstep - 2, DofGetDataCountGlobal(T[0]), phgDofNormL2(T[0]));
      
	    phgDofGradient(u[0], &gradu[0], NULL, "gradu_{n}");
	    phgDofSetFunction(u[0], DofInterpolation);
	    phgDofSetFunction(p[0], DofInterpolation);
	    //phgDofSetBdryDataByFunction(u[0], func_u, SETFLOW);
	    DOF_SCALE(u[0], "resume");
	    DOF_SCALE(p[0], "resume");
	    DOF_SCALE(T[0], "resume");
	    DOF_SCALE(gradu[0], "resume");

	    elapsed_time(g, TRUE, phgPerfGetMflops(g, NULL, NULL));
	}

	/* resmue u_{n} */
	//sprintf(data_file, OUTPUT_DIR "/ins_" NS_PROBLEM "_%05d.dat", tstep - 1);
	sprintf(data_file, OUTPUT_DIR "/ins_" NS_PROBLEM "_%05d.dat", 2);
	DATA_FILE_SURFIX;
	sprintf(fname, "%s.p%03d", data_u, g->rank);
	if ((fp = fopen(fname, "r")) == NULL) {
	    phgError(1, "read Dof data %s failed!\n", data_file);
	} else {
	    fclose(fp);
	    load_dof_data3(g, u[1], data_u, mesh_file);
	    load_dof_data3(g, p[1], data_p, mesh_file);
	    load_dof_data3(g, T[1], data_T, mesh_file);
	    phgPrintf("   Resume u_ {%5d}[%8d]:%24.12E p_ {%5d}[%8d]:%24.12E\n", 
		      tstep - 1, DofGetDataCountGlobal(u[1]), phgDofNormL2(u[1]), 
		      tstep - 1, DofGetDataCountGlobal(p[1]), phgDofNormL2(p[1]));
	    phgPrintf("   Resume T_{%5d}[%8d]:%24.12E\n", 
		      tstep - 1, DofGetDataCountGlobal(T[1]), phgDofNormL2(T[1])); 
      
	    phgDofGradient(u[1], &gradu[1], NULL, "gradu_{n+1}");
	    phgDofSetFunction(u[1], DofInterpolation);
	    phgDofSetFunction(p[1], DofInterpolation);
	    //phgDofSetBdryDataByFunction(u[1], func_u, SETFLOW);
	    DOF_SCALE(u[1], "resume");
	    DOF_SCALE(p[1], "resume");
	    DOF_SCALE(T[1], "resume");
	    DOF_SCALE(gradu[1], "resume");

	    elapsed_time(g, TRUE, phgPerfGetMflops(g, NULL, NULL));
	}
#endif

	/* Re init height & depth */
	if (gL != NULL) {
	    get_height_depth(ns);
	    build_layered_mesh_height(g, gL);
	    check_height(g, gL);
	}


	/* reconstruct last time step */
	//Time -= dt[0];
	Time = tstep - 1;
	ns->time[1] = Time;
	ns->time[0] = Time;
	setFuncTime(Time);
#if 0
	phgExportEnsightT(g, OUTPUT_DIR "/ins_" NS_PROBLEM , tstep, tstep, u[1], p[1], NULL);
	phgFinalize();
	return 0;
#endif	/* debug exit */

    }	/* end of resume */


    /* Init temp field */
    DOF_SCALE(ns->beta, "test");
    if (ns_params->solve_temp && tstep == 1) {
        phgPrintf("Init temp field!\n");
	phgNSTempInit(ns);
    }

	
    /* ================================================================================
     *
     * 
     *    Main loop:
     *       1. Steady state:   adaptive refinement.
     *       2. Time dependent: time advance.
     *
     * ================================================================================
     */
    while (TRUE) {


    FLOAT all_memory_usage = phgMemoryUsage(g, NULL)/(1024.0*1024.0);
    if (all_memory_usage > 10000)
        break;

    get_surf_bot_elev(ns);
    DOF *grad_surf_elev = phgDofGradient(ns->surf_elev_P1, NULL, NULL, "gradu_surf_elev");
    ns->grad_surf_elev = grad_surf_elev;
    



        //phgPrintf("modify mask bot!!\n");
        //modify_mask_bot(ns);
        //modify_mask_bot(ns);

    //phgDofSetDataByValue(u[1], 0.);
    //phgDofSetDataByValue(p[1], 0.);

    ns->surf_bas = get_surface_bases(g, DOF_P2);
    surf_bas = ns->surf_bas;

	static BOOLEAN initialized = FALSE;
	FLOAT time_end = ns_params->time_end;

	elapsed_time(g, FALSE, 0.);	/* reset timer */
	phgGetTime(tt);

	if (Fabs(time_end - Time) < 1e-12) {
	    phgPrintf("\n=======\nTime reach end: %lf, exit.\n", Time);
    phgPrintf("Time End %f\n", time_end);
	    break;
	}

	if (tstep > ns_params->max_tstep) {
	    phgPrintf("\n=======\nTime step reach end: %d, exit.\n", 
		      tstep);
	    break;
	}

#if 0
	/* use time t^{n+1} */
	dt[-1] = dt[0];
	if (Time + dt[0] > time_end)
	    dt[0] = time_end - Time;

	Time += dt[0];
	setFuncTime(Time);
#endif

	phgPrintf("\n==========\ntime: %lf, step:%d\n", (double)Time, tstep);
	phgPrintf("    %d DOF (u:%d, p:%d), %d elements, %d submesh%s, load imbalance: %lg\n",
		  DofGetDataCountGlobal(u[1]) + DofGetDataCountGlobal(p[1]), 
		  DofGetDataCountGlobal(u[1]), DofGetDataCountGlobal(p[1]), 
		  g->nleaf_global, g->nprocs,
		  g->nprocs > 1 ? "es" : "", (double)g->lif);

	/* save mesh */
	if (ns_params->record
	    && tstep % ns_params->step_span == 0) {			
	    phgResumeLogUpdate(g, &Time, &tstep, ns_params->fn, NULL);
	}

	if (!initialized) {
	    /* reset mem_peak */
	    phgMemoryUsageReset();
	    initialized = TRUE;
	}




	/* ------------------------------------------------------------
	 * 
	 *   Time marching 
	 * 
	 * ------------------------------------------------------------ */
	/* update variale,  
	 *   call this routine after time update and/or grid change.*/
	phgNSTimeAdvance(ns, Time, tstep);
	phgPrintf("    update solution");
	elapsed_time(g, TRUE, 0.);
	if (ns_params->pin_node)
	    phgNSPinNode(ns);

	/* --------------------------------------------------------------------------------
	 * 
	 *  Step 3.
	 *
	 *  Momentum Equations.
	 *
	 * -------------------------------------------------------------------------------- */
    int mask_iter = 0, inverse_iter = 0;
    INT IF_CHANGE_MASK;

#if 1
    while (TRUE)
    {
        // iteration for ice shelf mask updating and inversion

    if ((inverse_iter % 2) == 0)

        ns->set_dirichlet_bc = 0;
        /* newton bc for the surface, i.e. normal simulation */

    else
        ns->set_dirichlet_bc = 1;
        /* constrain the surface with obs. vel. for inversion */

        
    
    phgPrintf("----------------------------\n");
    phgPrintf("ice shelf mask iteration: %d\n", mask_iter);
    phgPrintf("----------------------------\n");
	elapsed_time(g, FALSE, 0.);	/* reset timer */
	/*
	 * non-linear iteration.
	 * */
	int max_nonstep = 0, newton_start = 0;
	assert(ns_params->utype == DOF_P2);

	/* For nonlinear iter */
	int nonstep = 0; 
	non_du = non_dp = non_dT = 1e+10;
	DOF *u_last = phgDofCopy(u[1], NULL, NULL, "u_last");
	DOF *p_last = phgDofCopy(p[1], NULL, NULL, "p_last");

	FLOAT non_res_last = 1.;
	LTYPE ltype_last = PICARD;

	/* First step, change max non step.  */
	if (tstep == 1) {	
	    if (ns_params->max_nonstep0 > 0)
		max_nonstep = ns_params->max_nonstep0;
	    else
		max_nonstep = ns_params->max_nonstep;
	    if (ns_params->newton_start0 > 0)
		newton_start = ns_params->newton_start0;
	    else
		newton_start = ns_params->newton_start;
	    phgPrintf("   * Set max nonstep to %d for first step.\n", max_nonstep);
	    phgPrintf("   * Set Newton start to %d for first step.\n", newton_start);
	} else {
	    max_nonstep = ns_params->max_nonstep;
	    newton_start = ns_params->newton_start;
	}


	while (TRUE) {
	    phgPrintf("\n   ==================\n");
	    phgPrintf("   Non-linear interation step: %d\n", nonstep);
	    
	    /* Init const viscosity */
	    if (ns_params->start_const_vis &&
		tstep == 0 && nonstep == 0 && mask_iter == 0) {
		phgPrintf("* vis: const\n");
		ns->viscosity_type = VIS_CONST;
	    } else {		
		phgPrintf("* vis: strain\n");
		ns->viscosity_type = VIS_STRAIN;		
	    }
	    
	    sayHello("Non linear solve begin");
	    phgNSInitSolverU(ns);

        if (inverse_iter < 1)
            get_viscosity(ns);

        /* initiate viscosity field at the beginning
         * afterwards use the updated viscosity field */

	    if (nonstep < newton_start)
		ns->ltype = PICARD;
	    else 
		ns->ltype = NEWTON;

	    phgPrintf("   Build RHS: ");
	    phgNSBuildSolverURHS(ns, 1, nonstep, Time);
	    //phgNSBuildSolverURHS(ns);
	    elapsed_time(g, TRUE, phgPerfGetMflops(g, NULL, NULL));

	    ns->non_res = 
		res = phgVecNorm2(ns->solver_u->rhs, 0, NULL);
	    phgPrintf("   nonlinear residual: %24.12E\n", res);

	    /* Restore Picard if no improvement */
#if 1
	    if (ltype_last == NEWTON &&
		res > non_res_last * .75) {
		phgPrintf("   !!! Newton step failed, use Picard to run again\n");
		ns->ltype = PICARD;
		max_nonstep += 5; /* Add more Picard steps  */

		/* resotre dofs:
		 * Fix me: temprature */
		phgDofCopy(u_last, &u[1], NULL, "u_{n+1}");
		phgDofCopy(p_last, &p[1], NULL, "p_{n+1}");
		phgDofGradient(u[1], &gradu[1], NULL, "gradu_{n+1}");
		phgNSBuildSolverURHS(ns, 1, nonstep, Time);
		ns->non_res = 
		    res = phgVecNorm2(ns->solver_u->rhs, 0, NULL);
		phgPrintf("   nonlinear residual: %24.12E\n", res);
	    } 
#endif

	    /* save non res */
	    non_res_last = res;
	    ltype_last = ns->ltype;
	    
	    /* build matrices */
	    //if (ns_params->use_PCD)
		//phgNSInitPc(ns);

	    phgPrintf("   Build matrices:\n");
	    phgNSBuildSolverUMat(ns, 1, nonstep, Time);
	    //phgNSBuildSolverUMat(ns);
	    phgPrintf("      done ");

	    elapsed_time(g, TRUE, phgPerfGetMflops(g, NULL, NULL));

#if 0
	    if (ns_params->use_PCD) {
		phgPrintf("   Build Pc: \n");
		phgNSBuildPc(ns);
		phgPrintf("      done ");
		elapsed_time(g, TRUE, phgPerfGetMflops(g, NULL, NULL));
	    }
#endif


	    //elapsed_time(g, TRUE, phgPerfGetMflops(g, NULL, NULL));

	    /*
	     * solve equation and update (u, p)
	     * */
	    phgPrintf("solver tol: %E\n", ns->solver_u->rtol);


	    phgSolverSolve(ns->solver_u, TRUE, ns->du, ns->dp, NULL);


	   // elapsed_time(g, TRUE, phgPerfGetMflops(g, NULL, NULL));
        //get_water_pressure(ns);
#if USE_NODAL_LOADS
        get_nodal_force(ns);
        phgMatDestroy(&ns->matF0);
        phgMatDestroy(&ns->matB0);
        phgMatDestroy(&ns->matBt0);
        phgMatDestroy(&ns->matC0);
        //phgSolverDestroy(&ns->solver_u0);
        ns->solver_u0 = NULL;
#endif
        //get_contact(ns);


#if USE_SLIDING_BC
	    rotate_dof_bases(ns->du, surf_bas, FALSE);
#endif
	    phgPrintf("      solver_u: nits = %d, resid = %0.4lg ",
		      ns->solver_u->nits, ns->solver_u->residual);
	    //elapsed_time(g, TRUE, phgPerfGetMflops(g, NULL, NULL));

	    /* save dofs */
	    phgDofCopy(u[1], &u_last, NULL, "u_last");
	    phgDofCopy(p[1], &p_last, NULL, "p_last");
        phgExportVTK(g, "u_test.vtk", ns->u[1], NULL);

	    /* nonlinear correction */
	    phgDofAXPY(1.0, ns->du, &u[1]);
	    phgDofAXPY(1.0, ns->dp, &p[1]);
	    assert(u[1]->type == ns_params->utype);
	    assert(p[1]->type == ns_params->ptype);
#if USE_SLIDING_BC
	    //dof_set_normal_data(u[1], surf_bas);
#else
#endif

	    /* non_du = phgDofNormL2(ns->du); */
	    /* non_dp = phgDofNormL2(ns->dp); */
	    non_du = phgDofNormInftyVec(ns->du);
	    non_dp = phgDofNormInftyVec(ns->dp);
	    phgPrintf(" \n  du: %24.12E dp: %24.12E\n", non_du, non_dp);
	    phgPrintf("   u: [%24.12E, %24.12E]\n", 
		      phgDofMinValVec(u[1]), 
		      phgDofMaxValVec(u[1]));
	    phgPrintf("   p: [%24.12E, %24.12E]\n", 
		      phgDofMinValVec(p[1]), 
		      phgDofMaxValVec(p[1]));
	    phgDofGradient(u[1], &gradu[1], NULL, "gradu_{n+1}");
        //get_avg_gu(ns);
        //gradu[1] = ns->avg_gu;

	    //elapsed_time(g, TRUE, phgPerfGetMflops(g, NULL, NULL));

	    //if (ns_params->use_PCD)
		//phgNSDestroyPc(ns);
        //

	    /* evolution of u */
	    //DOF_SCALE(u[1], "after solve");
	    //DOF_SCALE(p[1], "after solve");
#if 0
#  warning check solution U,p
	    sprintf(vtk_file, OUTPUT_DIR "non_%02d_u.vtk", nonstep);
	    phgExportVTK(g, vtk_file, u[1], p[1], NULL);
	    phgExportEnsightT(g, OUTPUT_DIR "ins_" NS_PROBLEM ,
			      nonstep, nonstep, u[1], p[1], T[1],
			      ns->du, ns->dp, ns->dT, NULL);
#endif



#if 0
	    if (FALSE && nonstep % ns_params->step_span == 0) {
		phgPrintf("   Output solution to ensight ");
		phgExportEnsightT(g, OUTPUT_DIR "/ins_" NS_PROBLEM , nonstep, nonstep,
				  u[1], p[1], T[1], NULL);  /* ensight */
		sprintf(vtk_file, OUTPUT_DIR "non_%02d_T.vtk", nonstep);
		phgExportVTK(g, vtk_file , 
			     u[1], p[1], T[1], ns->du, NULL);
		elapsed_time(g, TRUE, 0.);
		//ice_monitor(ns, nonstep);
	    }
#endif


	    /* Linearized */
#if 0
	    if (!ns_params->non_linear
		&& nonstep >= 0) {
		phgPrintf("   Linearized iteration converges.\n");
		break;
	    }
#endif

	    phgGetTime(tt1);
	    phgPrintf("    time usage of current non step: %lfs\n",
		      (double)(tt1[2] - tt[2]));

	    nonstep++;

	    /*
	     * Nonliner iteration break, 
	     *   converge for characteristic value.
	     * Velocity: 100 m/a
	     * Pressure: 1e8 Pa
	     *
	     *  */

        
        INT u_convergence;

        if (mask_iter < 1)
            u_convergence = check_u_convergence0(ns, u[1], p[1], u_last, p_last, ns_params->u_tol0, ns_params->u_tol0);
        else
            u_convergence = check_u_convergence(ns, u[1], p[1], u_last, p_last, ns_params->u_tol, ns_params->u_tol);


	    //elapsed_time(g, TRUE, phgPerfGetMflops(g, NULL, NULL));

	    const FLOAT U0 = 100;
	    const FLOAT P0 = 1e8;
	    if ( nonstep >= ns_params->min_nonstep 
            && ns->viscosity_type != VIS_CONST 
            && u_convergence
		    || nonstep > ns_params->max_nonstep)
        {

            if (nonstep > ns_params->max_nonstep) 
            {
                phgPrintf("   Non-linear iteration reach max step,"
                       " results may be inaccrate!\n");
#if 1 && USE_NODAL_LOADS
                /*
                get_nodal_force(ns);
                phgMatDestroy(&ns->matF0);
                phgMatDestroy(&ns->matB0);
                phgMatDestroy(&ns->matBt0);
                phgMatDestroy(&ns->matC0);
                //phgSolverDestroy(&ns->solver_u0);
                ns->solver_u0 = NULL;
                */
                
                phgMatDestroy(&ns->matF);
                phgMatDestroy(&ns->matB);
                phgMatDestroy(&ns->matBt);
                phgMatDestroy(&ns->matC);
                phgSolverDestroy(&ns->solver_u);
                ns->solver_u = NULL;
                phgMapDestroy(&ns->Vmap);
                phgMapDestroy(&ns->Pmap);
                phgDofFree(&ns->u_shape);
                phgDofFree(&ns->p_shape);
#endif
                break;
            }
            else
            {
                phgPrintf("   Non-linear iteration converges.\n");
#if 1 && USE_NODAL_LOADS
                /*
                get_nodal_force(ns);
                phgMatDestroy(&ns->matF0);
                phgMatDestroy(&ns->matB0);
                phgMatDestroy(&ns->matBt0);
                phgMatDestroy(&ns->matC0);
                //phgSolverDestroy(&ns->solver_u0);
                ns->solver_u0 = NULL;
                */
                phgMatDestroy(&ns->matF);
                phgMatDestroy(&ns->matB);
                phgMatDestroy(&ns->matBt);
                phgMatDestroy(&ns->matC);
                phgSolverDestroy(&ns->solver_u);
                ns->solver_u = NULL;
                phgMapDestroy(&ns->Vmap);
                phgMapDestroy(&ns->Pmap);
                phgDofFree(&ns->u_shape);
                phgDofFree(&ns->p_shape);
#endif
                break;
            }
        }

	    phgNSDestroySolverU(ns);
       
	} /* solve */

	phgDofFree(&u_last);
	phgDofFree(&p_last);


	//phgPrintf("Save Dofs\n");
	//save_dof_data3(g, u[1], OUTPUT_DIR"u.dat");
	//save_dof_data3(g, p[1], OUTPUT_DIR"p.dat");

#elif 0
	/* Set velocity, for debugging */
	ns->viscosity_type = VIS_STRAIN;
	phgDofSetDataByFunction(u[1], func_u0);
	//phgDofSetDataByFunction(p[1], func_p0);
	phgDofGradient(u[1], &gradu[1], NULL, "gradu_{n+1}");
#else
	phgPrintf("Load Dofs\n");

	load_dof_data3(g, u[1], OUTPUT_DIR"u.dat", NULL);
	load_dof_data3(g, p[1], OUTPUT_DIR"p.dat", NULL);
#endif


	/* Project to continuous gradu */

#if 1
    phgPrintf("\n ======================= \n");
    phgPrintf("project velocity gradient");
    phgPrintf("\n======================== \n");
	proj_gradu(ns, ns->gradu[1]);
#endif


	//DOF_SCALE(gradu[1], "grad u");
	//DOF_SCALE(ns->Gradu, "Grad u");

    phgPrintf("\n----------------------------\n");
    phgPrintf("check ice shelf mask status");
    phgPrintf("\n----------------------------\n");


    get_mask_bot(ns);

    if (!(ns_params->another_run_with_updated_mask))
    {

        mask_iter = 1;

        phgPrintf("manually stops another run with updated mask!\n\n\n");


        IF_CHANGE_MASK = if_update_shelf_mask(ns);
        IF_CHANGE_MASK = 0;
        get_mask_bot(ns);
        if (tstep % ns_params->step_span == 0) { 
            phgPrintf("Save water and nodal forces to VTK \n");
            DOF *water_P1 = phgDofCopy(ns->water_force, NULL, DOF_P1, NULL);
            DOF *nodal_P1 = phgDofCopy(ns->nodal_force, NULL, DOF_P1, NULL);
            sprintf(vtk_file, MASK_OUTPUT_DIR "MASK_%05d.vtk", tstep);
            phgExportVTK(g, vtk_file, water_P1,nodal_P1,ns->contact_force,ns->mask_bot,NULL);
            phgDofFree(&water_P1);phgDofFree(&nodal_P1);
        }
    }

    if (mask_iter < 1)
    {
    IF_CHANGE_MASK = if_update_shelf_mask(ns);
    }



    if ((ns_params->another_run_with_updated_mask)){
    if (IF_CHANGE_MASK == 0)
    {
        phgPrintf("The lower surface mask remains unchanged. Stop the iteration of mask updating !\n");

        if (tstep % ns_params->step_span == 0) { 
            get_mask_bot(ns);
            phgPrintf("Save water and nodal forces to VTK \n");
            DOF *water_P1 = phgDofCopy(ns->water_force, NULL, DOF_P1, NULL);
            DOF *nodal_P1 = phgDofCopy(ns->nodal_force, NULL, DOF_P1, NULL);
            sprintf(vtk_file, MASK_OUTPUT_DIR "MASK_%05d.vtk", tstep);
            phgExportVTK(g, vtk_file, water_P1,nodal_P1,ns->contact_force,ns->mask_bot,NULL);
            phgDofFree(&water_P1);phgDofFree(&nodal_P1);
        }

        phgDofFree(&ns->nodal_force);
        phgDofFree(&ns->water_force);
        phgDofFree(&ns->contact_force);

        break;
    }
    }

    get_strain_rate(ns);

    if (ns->set_dirichlet_bc) {

        //DOF *u_d = phgDofCopy(ns->u[1], NULL, DOF_P2, NULL);
        DOF *eu_d = phgDofCopy(ns->strain_rate, NULL, DOF_P1, NULL);
        ns->eu_d = eu_d;

    }
    else {

        //DOF *u_n = phgDofCopy(ns->u[1], NULL, DOF_P2, NULL);
        DOF *eu_n = phgDofCopy(ns->strain_rate, NULL, DOF_P1, NULL);
        ns->eu_n = eu_n;

    }


    DOF *visc_old = phgDofCopy(ns->viscosity, NULL, DOF_P1, NULL);

    if (inverse_iter > 0)
        update_viscosity_inversion(ns);

    FLOAT tol = 0.01;
    INT visc_convergence = check_visc_convergence(ns, visc_old, tol);


    if((mask_iter >= 1) && (inverse_iter > 0) && (visc_convergence == 1))
    {
        phgPrintf("\n-------------------------\n");
        phgPrintf("ice shelf mask updated \n");
        phgPrintf("--------------------------\n");
        break;
    }


    if (mask_iter < 1)
    if (tstep % ns_params->step_span == 0) { 
        phgPrintf("Save water and nodal forces to VTK \n");
        DOF *water_P1 = phgDofCopy(ns->water_force, NULL, DOF_P1, NULL);
        DOF *nodal_P1 = phgDofCopy(ns->nodal_force, NULL, DOF_P1, NULL);
        sprintf(vtk_file, MASK_OUTPUT_DIR "MASK_%05d.vtk", tstep);
        phgExportVTK(g, vtk_file, water_P1,nodal_P1,ns->contact_force,ns->mask_bot,NULL);
        phgDofFree(&water_P1);phgDofFree(&nodal_P1);
    }
    

    phgDofFree(&ns->nodal_force);
    phgDofFree(&ns->water_force);
    phgDofFree(&ns->contact_force);


    //phgDofFree(&ns->mask_bot);

    //phgDofFree(&ns->water_pressure);
    //phgDofFree(&ns->stress_nn);
    //    phgPrintf("Free stress_nn !\n");
    //phgDofFree(&ns->stress);

    //phgDofFree(&ns->water_pressure1);
    //phgDofFree(&ns->stress_nn1);
    //phgDofFree(&ns->stress1);
    //phgDofFree(&ns->avg_gu);

    mask_iter++;
    inverse_iter++;

    }


        proj_gradu(ns, ns->gradu[1]);

        get_stress(ns, ns->gradu[1], ns->p[1]);



#if 0
        if (1) {
            int i, k;
            DOF *Gu[DDim], *gu[DDim], *guDG0, *stress[DDim];
            guDG0 = phgDofCopy(ns->gradu[1], NULL, DOF_P0, NULL);

            for (k = 0; k < DDim; k++) {
            FLOAT *vGu;
            INT n;
            char name[1000];

            sprintf(name, "Gu%d", k);
            Gu[k] = phgDofNew(g, DOF_P1, 1, name, DofNoAction);
            vGu = ns->Gradu->data; /* DOF_P1 */
            n = DofGetDataCount(Gu[k]);
            for (i = 0; i < n; i++)
                Gu[k]->data[i] = vGu[i * DDim + k];

            sprintf(name, "stress%d", k);
            stress[k] = phgDofNew(g, DOF_P1, 1, name, DofNoAction);
            vGu = ns->stress->data; /* DOF_P1 */
            n = DofGetDataCount(stress[k]);
            for (i = 0; i < n; i++)
                stress[k]->data[i] = vGu[i * DDim + k];
            
            sprintf(name, "gu%d", k);
            gu[k] = phgDofNew(g, DOF_P0, 1, name, DofNoAction);
            vGu = guDG0->data;   /* DOF_P0 */
            n = DofGetDataCount(gu[k]);
            for (i = 0; i < n; i++)
                gu[k]->data[i] = vGu[i * DDim + k];
            }

            
            phgExportVTK(g, "stress.vtk",
                    stress[0], stress[1], stress[2],
                    stress[3], stress[4], stress[5],
                    stress[6], stress[7], stress[8],
                    NULL);

            phgExportVTK(g, "Gu.vtk",
                 Gu[0], Gu[1], Gu[2],
                 Gu[3], Gu[4], Gu[5],
                 Gu[6], Gu[7], Gu[8],
                 gu[0], gu[1], gu[2],
                 gu[3], gu[4], gu[5],
                 gu[6], gu[7], gu[8],
                 NULL);
           // phgFinalize();
        }
#endif






	/* --------------------------------------------------------------------------------
	 *
	 *  Step 4.
	 *
	 *   Solve temperature.
	 *
	 * -------------------------------------------------------------------------------- */

#if 1
	if (ns_params->solve_temp) {
	    phgPrintf("\n   ==================\n");
	    phgPrintf("   Temperature solve \n");
	    phgPrintf("   ==================\n\n");
	    phgPrintf("   T type: %s\n", T[1]->type->name);

	    elapsed_time(g, FALSE, 0.);	/* reset timer */

	    phgNSInitSolverT(ns);

	    phgPrintf("   Build Mat: ");
	    phgNSBuildSolverTMat(ns, FALSE);
	    elapsed_time(g, TRUE, phgPerfGetMflops(g, NULL, NULL));
	    phgPrintf("   Build RHS: ");
	    phgNSBuildSolverTRHS(ns, FALSE);
	    elapsed_time(g, TRUE, phgPerfGetMflops(g, NULL, NULL));

	    phgNSSolverTBuildConstrain(ns);
	    phgDofCopy(ns->T[1], &ns->dT, NULL, "dT");

	    phgNSSolverTSolve(ns, FALSE);
	    elapsed_time(g, TRUE, phgPerfGetMflops(g, NULL, NULL));

	    phgNSDestroySolverT(ns);

	    //find_melt_region(ns);
	    DOF_SCALE(ns->T[1], "after solve");
	    phgDofAXPY(-1.0, ns->T[1], &ns->dT);
	    non_dT = phgDofNormInftyVec(ns->dT);
	    phgPrintf("   dT: %24.12E\n", non_dT);


	    DOF *temp_diff = phgDofCopy(ns->T[1], NULL, NULL, "Td");
	    {
		FLOAT *vt = temp_diff->data;
		const FLOAT *vh = ns->depth_P2->data;

		INT i, n = DofGetDataCount(temp_diff);
		for (i = 0; i < n; i++, vh++, vt++)
		    *vt = TEMP_WATER - BETA_MELT * (*vh) *LEN_SCALING  - (*vt);
	    }
	} else {
	    phgPrintf("Temp not updated.\n");
	    non_dT = 0.;
	}
#endif




	/* ------------------------------------------------------------
	 * 
	 *   Error check
	 * 
	 * ------------------------------------------------------------ */

#if 0
	if (!ns_params->compute_error) {
	    eu = ep = egradu = eT = NULL;
	    ediv = phgDofDivergence(u[1], NULL, NULL, "err div u");
	    phgPrintf(            "            normL2(u, p) = (%20.12E, %20.12E)\n"
				  "            normH1(u)    = (%20.12E)\n"
				  "            normDiv(u)   = (%20.12E)\n"
				  "            normGadu    = (%20.12E)\n",
				  dofNormL2(u[1]), dofNormL2(p[1]),
				  dofNormL2(gradu[1]), dofNormL2(ediv),
				  dofNormL2(ns->gradu[1]));
	    elapsed_time(g, TRUE, 0.);
	} else {
	    /* ----Error check------- */
	    phgPrintf("    Errors: \n");
	    eu = phgDofCopy(u[1], NULL, ns_params->utype, "erru");
	    ep = phgDofCopy(p[1], NULL, ns_params->ptype, "errp");
	    eT = phgDofCopy(T[1], NULL, NULL, "errT");
	    egradu = phgDofCopy(gradu[1], NULL, NULL, "err grad u");
	    ediv = phgDofDivergence(u[1], NULL, NULL, "err div u");

	    adjust_time(- (1. - ns_params->Theta) * dt[0]);
	    restore_time();

	    phgPrintf("            errL2(u, p) = (%20.12E, %20.12E)\n"
		      "            errH1(u)    = (%20.12E)\n"
		      "            errDiv(u)   = (%20.12E)\n",
		      dofNormL2(eu), dofNormL2(ep),
		      dofNormL2(egradu), dofNormL2(ediv));
	    elapsed_time(g, TRUE, 0.);
	    phgDofFree(&egradu);

	    dof_norm_L2(eT);
	}
#endif


	getPecletNum(g, u[1], ns_params->nu, 6);	
	mem = phgMemoryUsage(g, &mem_peak);
	phgPrintf("    Memory usage: current %0.4lgMB, peak %0.4lgMB\n",
		  (double)mem / (1024.0 * 1024.0),
		  (double)mem_peak / (1024.0 * 1024.0));





	/* ------------------------------------------------------------
	 * 
	 *   Move mesh
	 * 
	 * ------------------------------------------------------------ */
    FLOAT ice_volume_last = get_ice_volume(g);
//	DOF *dH_last = phgDofCopy(ns->dH, NULL, NULL, "dH_last");

	if (ns_params->solve_height) {
	    if (gL != NULL) {
		/* Unstructed layered mesh */
		phgPrintf("Move mesh.\n");
        get_surf_dH(ns);
        //DOF *dH_fem = phgDofCopy(ns->dH, NULL, NULL, NULL);
        phgExportVTK(g, "dH_fem1.vtk", ns->dH, NULL);
        get_smooth_surface_values(ns, ns->dH, 0);
        get_smooth_surface_values(ns, ns->dH, 1);
        phgExportVTK(g, "dH_fem.vtk", ns->dH, NULL);

        /*
        save_free_surface_elev(ns, 0);
        save_free_surface_elev(ns, 1);

        save_free_surface_velo(ns, 0, 0);
        save_free_surface_velo(ns, 1, 0);
        save_free_surface_velo(ns, 2, 0);
        save_free_surface_velo(ns, 0, 1);
        save_free_surface_velo(ns, 1, 1);
        save_free_surface_velo(ns, 2, 1);

        if (phgRank == 0)
        {
            system("python get_upper_ds.py");
            system("python get_lower_ds.py");
        }

        load_dH_from_file(ns, ns->dH, 0);
        load_dH_from_file(ns, ns->dH, 1);
        //DOF *dH_fdm = phgDofCopy(ns->dH, NULL, NULL, NULL);

        //phgDofAXPY(-1, dH_fem, &dH_fdm);

        //phgExportVTK(g, "dH_diff.vtk", dH_fdm, NULL);
        *///phgExportVTK(g, "dH_fdm.vtk", ns->dH, NULL);

		get_moved_coord(ns, tstep);
        phgExportVTK(g, "dH_fem2.vtk", NULL);
		move_mesh(ns);
        //phgExportVTK(g, "moved_geo.vtk", NULL);
		//check_height(g, gL);
	    } else {
		/* Structed layered mesh */
		struct_mesh_update(ns, tstep, Time);
	    }

	    phgDofGradient(u[1], &gradu[1], NULL, "gradu_{n+1}");
	    phgDofGradient(u[0], &gradu[0], NULL, "gradu_{n}");
	} else {
	    phgPrintf("Mesh not moved.\n");
	}

    phgPrintf("\n-----------------------------------------\n");
    phgPrintf("   dH: [%4.2E, %4.2E]\n", 
          phgDofMinValVec(ns->dH), 
          phgDofMaxValVec(ns->dH));
    phgPrintf("------------------------------------------\n\n");

    FLOAT ice_volume = get_ice_volume(g);

    //DOF *u_P1 = phgDofCopy(u[1], NULL, DOF_P1, NULL);
    //phgExportVTK(g, "u_P1.vtk", u_P1, NULL);

#if 1
    //INT dH_convergence = check_surf_convergence(ns, dH_last);

    
    //if (dH_convergence == 1)
    FLOAT dVdt = fabs(ice_volume-ice_volume_last)/ice_volume/dt[0]; 


    if (Time > 10 && dVdt < ns_params->s_tol)
    {
        phgPrintf("-----------------------------------------------------\n");
        phgPrintf("The ice domain reaches a steady state! Model stops! dVdt %e", dVdt);
        phgPrintf("\n-----------------------------------------------------\n");

        break;
    }
    else
    {
        phgPrintf("\n--------------------------------------------------------------\n");
        phgPrintf("The ice domain is still in an unsteady state! Model continues! dVdt %e\n", dVdt);
        phgPrintf("---------------------------------------------------------------\n\n");
    }
#endif
        


    
    update_grounding_line(ns, tstep);
       // after we update the geometry, we need to check the ice shelf mask again





	/* ------------------------------------------------------------
	 * 
	 *   Output solution
	 * 
	 * ------------------------------------------------------------ */
	if (tstep % ns_params->step_span == 0) { 
	    //ice_monitor(ns, tstep);

#if 1
	    /*  Temp check */
	    phgPrintf("    Output solution to VTK");
/* 	    phgExportEnsightT(g, OUTPUT_DIR "/ins_" NS_PROBLEM , Time, tstep, */
/* 	    		      u[1], p[1], T[1], ns->depth_P1, */
/* 	    		      NULL);  /\* ensight *\/ */
        DOF *u_P1 = phgDofCopy(u[1], NULL, DOF_P1, NULL);
        //phgExportVTK(g,"results.vtk",u_P1,p[1],NULL);
	    sprintf(vtk_file, dH_OUTPUT_DIR "ice_%05d.vtk", tstep);
	    phgExportVTK(g, vtk_file, u_P1, NULL);
        phgDofFree(&u_P1);
	    sprintf(vtk_file, dH_OUTPUT_DIR "dH_%05d.vtk", tstep);
	    phgExportVTK(g, vtk_file, ns->dH, NULL);
	    sprintf(vtk_file, dH_OUTPUT_DIR "stress_%05d.vtk", tstep);
	    phgExportVTK(g, vtk_file, ns->stress, NULL);
	    //sprintf(vtk_file, OUTPUT_DIR "mask_%05d.vtk", tstep);
	    //phgExportVTK(g, vtk_file, ns->mask_bot, NULL);
	    

	    elapsed_time(g, TRUE, 0.);
#endif

	    /* Save coord data */
#if 1
	if (tstep % ns_params->step_span_resume == 0) { 
	    {
		//sprintf(data_Crd, OUTPUT_DIR "/ins_" NS_PROBLEM "_%05d.dat.Crd", tstep);
		sprintf(data_Crd, OUTPUT_DIR "/ins_" NS_PROBLEM "_%05d.dat.Crd", 2);
		assert(ns->coord->type == DOF_P1);
		save_dof_data3(g, ns->coord, data_Crd);
	    }

	    if (ns_params->record) {			
		/* save dof data for time step {n}, {n+1} */
		//sprintf(data_file, OUTPUT_DIR "/ins_" NS_PROBLEM "_%05d.dat", tstep - 1);
		sprintf(data_file, OUTPUT_DIR "/ins_" NS_PROBLEM "_%05d.dat", 1);
		DATA_FILE_SURFIX;
		save_dof_data3(g, u[0], data_u);
		save_dof_data3(g, p[0], data_p);
		save_dof_data3(g, T[0], data_T);
		phgPrintf("   Save u_ {%5d}[%8d]:%24.12E p_ {%5d}[%8d]:%24.12E\n", 
			  tstep - 1, DofGetDataCountGlobal(u[0]), phgDofNormL2(u[0]), 
			  tstep - 1, DofGetDataCountGlobal(p[0]), phgDofNormL2(p[0]));
		phgPrintf("   Save T_{%5d}[%8d]:%24.12E\n", 
			  tstep - 1, DofGetDataCountGlobal(T[0]), phgDofNormL2(T[0])); 
		DOF_SCALE(u[0], "save");
		DOF_SCALE(p[0], "save");
		DOF_SCALE(T[0], "save");
		DOF_SCALE(gradu[0], "save");
		

		//sprintf(data_file, OUTPUT_DIR "/ins_" NS_PROBLEM "_%05d.dat", tstep);
		sprintf(data_file, OUTPUT_DIR "/ins_" NS_PROBLEM "_%05d.dat", 2);
		DATA_FILE_SURFIX;
		save_dof_data3(g, u[1], data_u);
		save_dof_data3(g, p[1], data_p);
		save_dof_data3(g, T[1], data_T);
		phgPrintf("   Save u_ {%5d}[%8d]:%24.12E p_ {%5d}[%8d]:%24.12E\n", 
			  tstep, DofGetDataCountGlobal(u[1]), phgDofNormL2(u[1]), 
			  tstep, DofGetDataCountGlobal(p[1]), phgDofNormL2(p[1]));
		phgPrintf("   Save T_{%5d}[%8d]:%24.12E\n", 
			  tstep, DofGetDataCountGlobal(T[1]), phgDofNormL2(T[1]));
		DOF_SCALE(u[1], "save");
		DOF_SCALE(p[1], "save");
		DOF_SCALE(T[1], "save");
		DOF_SCALE(gradu[1], "save");
		phgResumeLogUpdate(g, NULL, NULL, NULL, data_file);
	    } /* end of record */
	    if (gL != NULL) {
		    //check_height(g, gL);
        }
	    sayHello("After record final solution data");
    }
#endif

	}



    //phgDofFree(&dH_last);
	/* clean up */
	//phgDofFree(&ediv);
	//phgDofFree(&eu);
	//phgDofFree(&ep);
	//phgDofFree(&eT);



	/* ----------------------------------------------------------------------
	 * 
	 * Compute drag force FD
	 *
	 * ---------------------------------------------------------------------- 
	 * */






        phgGetTime(tt1);
        phgPrintf("    total time usage of current time step: %lfs\n",
		  (double)(tt1[2] - tt[2]));

	if (mem_peak > 1024 * (size_t)ns_params->mem_max * 1024) {
	    phgPrintf("\n=======\nMem usage reach max, exit.\n");
	    break;
	}
	tstep++;


#if 1
	/* use time t^{n} */
	dt[-1] = dt[0];
	if (Time + dt[0] > time_end)
	    dt[0] = time_end - Time;

	Time += dt[0];
	setFuncTime(Time);
#endif

    phgDofFree(&surf_bas->dof);
    phgDofFree(&ns->surf_bas->dof);
    }				/* end of time advaning */



    /* destroy line block */
    //destroy_line_block(&ns->bk);

    /* destroy reused solver */
    if (ns->solver_u != NULL) {
	if (ns_params->use_PCD)
	    phgNSDestroyPc(ns);
	phgNSDestroySolverU(ns);
    }


    phgNSFinalize(&ns);
	    
    phgFreeGrid(&g);
    phgFinalize();
    phgFree(ns_params);

    return 0;
}
Esempio n. 6
0
/* Get local bases for boundary vertex i,
 *  return num of constrained bases, 
 *  and noramlized direction of rotated bases.
 *  */
SURF_BAS *
get_surface_bases(GRID *g, DOF_TYPE *u_type)
{
    SIMPLEX *e;
    DOF *surf_dof = NULL, *norm_lat = NULL, *norm_bot = NULL;
    BOOLEAN *rotated = NULL;
    INT nrot = 0;
    surf_dof = phgDofNew(g, u_type, DDim, "Surf bases", DofNoAction);
    
    //norm_lat = phgDofNew(g, u_type, Dim, "Norm lateral", DofNoAction);
    //norm_bot = phgDofNew(g, u_type, Dim, "Norm Bottom", DofNoAction);
    //DOF *coord = phgDofNew(g, u_type, Dim, "coord", func_xyz_);
	DOF *avg_n = phgDofNew(g, DOF_P2, 3, "avg n", DofNoAction);
        get_avg_n(g, avg_n);
    
    rotated = phgCalloc(DofGetDataCount(surf_dof) / (DDim), sizeof(*rotated));
    SURF_BAS *surf_bas;

    surf_bas = phgCalloc(1, sizeof(*surf_bas));
    surf_bas->type = u_type;
    //surf_bas->dof = phgDofNew(g, u_type, DDim, "Surf bases", DofNoAction);//surf_dof;
    //surf_bas->dof = surf_dof;
    surf_bas->rotated = rotated;
    phgDofSetDataByValue(surf_dof, 0.);
    //phgDofSetDataByValue(surf_bas->dof, 0.);
    
    //phgDofSetDataByValue(norm_lat, -99.);
    //phgDofSetDataByValue(norm_bot, -99.);
    
        ForAllElements(g, e) {
	int s, ii, i, m, dof_i;
	int N = surf_dof->type->nbas;
	//int N = surf_bas->dof->type->nbas;
	FLOAT *avg_n_v;
	FLOAT normal[Dim];
	int  v[3];
	FLOAT norm;
	FLOAT norm_value_lat[N][Dim];
	FLOAT norm_value_bot[N][Dim];
	FLOAT bas_value[N][DDim],  H[Dim][Dim], c[Dim], 
	    bxyz[Dim][Dim] = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}};

	phgDofGetElementData(surf_dof, e, &bas_value[0][0]);
	//phgDofGetElementData(surf_bas->dof, e, &bas_value[0][0]);
	
	for (s = 0; s < NFace; s++) { 
	    int nbas_face = NbasFace(surf_dof);
	    //int nbas_face = NbasFace(surf_bas->dof);
	    INT id; 
	    SHORT ibas_face[nbas_face];

        //FLOAT *normal = phgGeomGetFaceOutNormal(g, e, s);

        //if (!((e->bound_type[s] & BC_BOTTOM) && !(e->bound_type[s] & BC_ISHELF)))
        if (!(e->bound_type[s] & BC_BOTTOM))
            continue;

	    phgDofGetBasesOnFace(surf_dof, e, s, ibas_face);
	    //phgDofGetBasesOnFace(surf_bas->dof, e, s, ibas_face);
	    for (ii = 0; ii < nbas_face; ii++) {
		i = ibas_face[ii];
		dof_i = phgDofMapE2D(avg_n, e, i*Dim);
		avg_n_v = DofData(avg_n);
		normal[0] = avg_n_v[dof_i + 0];
		normal[1] = avg_n_v[dof_i + 1];
		normal[2] = avg_n_v[dof_i + 2];
        /* i means the base function number in the element */
		/* Use Gram–Schmidt process to get orthogonal bases, 
		 * one constrains */

		id = phgDofMapE2D(surf_dof, e, i * (DDim)) / (DDim);
		//id = phgDofMapE2D(surf_bas->dof, e, i * (DDim)) / (DDim);
		rotated[id] = TRUE;
		nrot++;
		
		BTYPE elem_btype = phgDofGetElementBoundaryType(surf_dof, e, i*DDim);
		//BTYPE elem_btype = phgDofGetElementBoundaryType(surf_bas->dof, e, i*DDim);


		/* fisrt basis */
		memcpy(H[0], normal, Dim * sizeof(FLOAT));

		/* second basis */
		for (m = 0; m < Dim; m++)
		    if (fabs(c[0] = INNER_PRODUCT(H[0], bxyz[m])) < 0.9)
			break;
		assert(m < Dim);
	
		H[1][0] = bxyz[m][0] - c[0] * H[0][0]; 
		H[1][1] = bxyz[m][1] - c[0] * H[0][1]; 
		H[1][2] = bxyz[m][2] - c[0] * H[0][2]; 
		norm = sqrt(INNER_PRODUCT(H[1], H[1]));
		assert(norm > 1e-10);
		H[1][0] /= norm;
		H[1][1] /= norm;
		H[1][2] /= norm;
		H[1][0] = 0;
		H[1][1] = 1;
		H[1][2] = 0;

		/* third basis */
		for (m++; m < Dim; m++)
		    if (fabs(c[0] = INNER_PRODUCT(H[0], bxyz[m])) < 0.9)
			break;
		assert(m < Dim);
		//c[1] = INNER_PRODUCT(H[1], bxyz[m]);
		c[1] = H[1][0]*(bxyz[m][0] - c[0] * H[0][0])+H[1][1]*(bxyz[m][1] - c[0] * H[0][1]) + H[1][2]*(bxyz[m][2] - c[0] * H[0][2]);
		H[2][0] = bxyz[m][0] - c[0] * H[0][0] - c[1] * H[1][0]; 
		H[2][1] = bxyz[m][1] - c[0] * H[0][1] - c[1] * H[1][1];  
		H[2][2] = bxyz[m][2] - c[0] * H[0][2] - c[1] * H[1][2];  
		H[2][0] = H[0][1]*H[1][2] - H[0][2]*H[1][1];
		H[2][1] = H[0][2]*H[1][0] - H[0][0]*H[1][2];
		H[2][2] = H[0][0]*H[1][1] - H[0][1]*H[1][0];
		norm = sqrt(INNER_PRODUCT(H[2], H[2]));
		assert(norm > 1e-10);
		H[2][0] /= norm;
		H[2][1] /= norm;
		H[2][2] /= norm;
        	
        if ((elem_btype & BC_BOTTOM_GRD) && (elem_btype & BC_DIVIDE))
        {
			
            H[1][0] = 1;
            H[1][1] = 0;
            H[1][2] = 0;

            H[2][0] = (H[0][1]*H[1][2]-H[0][2]*H[1][1]);
            H[2][1] = -(H[0][0]*H[1][2]-H[0][2]*H[1][0]);
            H[2][2] = (H[0][0]*H[1][1]-H[0][1]*H[1][0]);
            
        }


#if 0
#  warning check use only: xyz coord ----------------------------
		memcpy(bas_value[i], bxyz[0], DDim*sizeof(FLOAT));
#else
		memcpy(bas_value[i], H[0], DDim*sizeof(FLOAT));
        /* bas_value is contains all bas values of all nodes in the element. 
         * For the nodes at the boundaries, bas value is real number, otherwise
         * bas value is just 0 */
#endif
	    } /* end bas */
	}     /* end face */
	phgDofSetElementData(surf_dof, e, &bas_value[0][0]);
	//phgDofSetElementData(surf_bas->dof, e, &bas_value[0][0]);
    }	      /* end elem */
/****************************************************************
 * Build RHS which is the residual of the nonlinear system.
 ***************************************************************/
static void
build_rhs(SOLVER *solver, SOLVER *pc, DOF **dofs, MAT **mats)
{
    DOF *u = dofs[0], *p = dofs[1];
    DOF *f, *pbc, *gn[3], *gradu, *divu, *lapu, *gradp, *f0;
    int M = u->type->nbas;	/* num of bases of Velocity */
    int i, k, s;
    GRID *g = u->g;
    ELEMENT *e;
    FLOAT bufu[M], resu[M][Dim], tmp[9];
    INT Iu[M][Dim];

    /* Unpack Dofs */
    unpackDof(dofs, 9, &u, &p, &gradu, &divu, &f, &pbc, &gn[0], &gn[1],
	      &gn[2]);
    lapu = phgDofDivergence(gradu, NULL, NULL, NULL);
    gradp = phgDofGradient(p, NULL, NULL, NULL);
    time -= dt;
    f0 = phgDofNew(g, DOF_HB6, 3, "p_n", func_f);
    time += dt;

    ForAllElements(g, e) {
	/* Map: Element -> system */
	for (i = 0; i < M; i++)
	    for (k = 0; k < Dim; k++)
		Iu[i][k] = phgMapE2L(solver->rhs->map, 0, e, i * Dim + k);

	/* Global Matrix */
	bzero(resu, sizeof(resu));
	for (i = 0; i < M; i++) {
	    /* Dirichle Boundary for velocity. */
	    if (phgDofDirichletBC(u, e, i, func_u, bufu, &resu[i][0],
				  DOF_PROJ_NONE)) {
		/* set velocity at Dirichlet bdry */
	    }
	    else {		/* interior node or Neumann */
		/* (u(t_n), \phi) */
		phgQuadDofTimesBas(e, u, u, i, QUAD_DEFAULT, tmp);
		for (k = 0; k < Dim; k++)
		    resu[i][k] = tmp[k];

		/* (f, \phi_i) */
		phgQuadDofTimesBas(e, f0, u, i, QUAD_DEFAULT, tmp);
		for (k = 0; k < Dim; k++)
		    resu[i][k] += dt * (1 - Theta) * tmp[k];

		phgQuadDofTimesBas(e, f, u, i, QUAD_DEFAULT, tmp);
		for (k = 0; k < Dim; k++)
		    resu[i][k] += dt * Theta * tmp[k];

		/* -( ((u.\grad) u, \phi) */
		phgQuadDofDotGradDofBas(e, u, gradu, i, QUAD_DEFAULT, tmp);
		for (k = 0; k < Dim; k++)
		    resu[i][k] -= dt * (1 - Theta) * tmp[k];

		/* +\nu ( lap(u(t_n)), \phi) */
		phgQuadDofTimesBas(e, lapu, u, i, QUAD_DEFAULT, tmp);
		for (k = 0; k < Dim; k++)
		    resu[i][k] += (1 - Theta) * dt * nu * tmp[k];

		/* -(gradp(t_n), \phi) */
		phgQuadDofTimesBas(e, gradp, u, i, QUAD_DEFAULT, tmp);
		for (k = 0; k < Dim; k++)
		    resu[i][k] -= (1 - Theta) * dt * tmp[k];
	    }
	}			/* end of Block (1,1), (1,2) */

	/* Neumann Bdry */
	for (s = 0; s < NFace; s++) {
	    if (e->bound_type[s] & NEUMANN) {
		SHORT bases[NbasFace(u)];
		phgDofGetBasesOnFace(u, e, s, bases);

		for (i = 0; i < NbasFace(u); i++) {
		    if (phgDofGetElementBoundaryType(u, e, bases[i] * Dim)
								& DIRICHLET) {
			/* Dirichlet bas on Neumann face, do nothing */
		    }
		    else if (phgDofGetElementBoundaryType(u, e, bases[i] * Dim)
								& NEUMANN) {
			for (k = 0; k < Dim; k++)
			    resu[bases[i]][k] += dt * Theta *
				phgQuadFaceDofDotBas(e, s, gn[k],
						     DOF_PROJ_DOT, u,
						     bases[i], QUAD_DEFAULT);
		    }
		    else {
			fprintf(stderr, "Warning: unkown bdry!");
		    }
		}		/* end of base on face */
	    }			/* end of face neu */
	}			/* end of all neumann face in element */

	/* Global res */
	phgSolverAddRHSEntries(solver, M * Dim, Iu[0], &resu[0][0]);
    }				/* end element */

    solver->rhs_updated = FALSE;
    phgDofFree(&lapu);
    phgDofFree(&gradp);
    phgDofFree(&f0);
    return;
}
Esempio n. 8
0
int
main(int argc, char *argv[])
{
  ELEMENT *e;
  GRID *g;
  DOF *u, *v, *u_hp, *v_hp;
  HP_TYPE *hp;
  MAP *map;
  char *fn = "cube.dat";
  char *dof_u = "P2", *dof_v = "P1";
  INT step = 0, pre_refines = 0;

  phgOptionsRegisterFilename("-mesh_file", "Mesh file", &fn);
  phgOptionsRegisterInt("-pre_refines", "Pre-refinements", &pre_refines);
  phgOptionsRegisterString("-dof_u", "DOF type for u", &dof_u);
  phgOptionsRegisterString("-dof_v", "DOF type for v", &dof_v);

  phgInit(&argc, &argv);
  g = phgNewGrid(-1);
  if (!phgImport(g, fn, FALSE))
    phgError(1, "can't read file \"%s\".\n", fn);
  phgRefineAllElements(g, pre_refines);

  phgOptionsSetHandler("-dof_type", dof_u);
  u = phgDofNew(g, DOF_DEFAULT, 1, "u", DofInterpolation);
  phgOptionsSetHandler("-dof_type", dof_v);
  v = phgDofNew(g, DOF_DEFAULT, 1, "v", DofInterpolation);
  phgPrintf("u->type = %s, v->type = %s\n", u->type->name, v->type->name);

  hp = phgHPNew(g, HP_HB);
  u_hp = phgHPDofNew(g, hp, 1, "u_hp", DofInterpolation);
  phgHPFree(&hp);
  hp = phgHPNew(g, HP_HC);
  v_hp = phgHPDofNew(g, hp, 1, "v_hp", DofInterpolation);
  phgHPFree(&hp);

  while (TRUE) {
    if (phgBalanceGrid(g, 1.1, 1, NULL, 0.))
      phgPrintf("Repartition mesh, %d submeshes, load imbalance: %lg\n",
		g->nprocs, (double)g->lif);

    phgPrintf("Testing map with non HP DOFs:\n");
    map = phgMapCreate(u, v, NULL);
    phgPrintf("    nlocal = %d, nglobal = %d\n", map->nlocal, map->nglobal);
    phgMapDestroy(&map);

    phgPrintf("Testing map with HP DOFs:\n");
    ForAllElements(g, e)
	e->hp_order = 1 + GlobalElement(g, e->index) % 4;
    phgHPSetup(u_hp->hp, FALSE);

    ForAllElements(g, e)
	e->hp_order = 1 + (3 - GlobalElement(g, e->index) % 4);
    phgHPSetup(v_hp->hp, FALSE);

    map = phgMapCreate(u_hp, v_hp, NULL);
    phgPrintf("    nlocal = %d, nglobal = %d\n", map->nlocal, map->nglobal);
    phgMapDestroy(&map);

    phgPrintf("Testing map with HP and non HP DOFs:\n");
    map = phgMapCreate(u, u_hp, v, v_hp, NULL);
    phgPrintf("    nlocal = %d, nglobal = %d\n", map->nlocal, map->nglobal);
    phgMapDestroy(&map);

    if (++step >= 1)
	break;
    phgRefineAllElements(g, 1);
  }

  phgDofFree(&u_hp);
  phgDofFree(&v_hp);
  phgDofFree(&u);
  phgDofFree(&v);

  phgFreeGrid(&g);
  phgFinalize();

  return 0;
}
Esempio n. 9
0
int
main(int argc, char *argv[])
{
    GRID *g;
    DOF *u_h;
    MAT *A, *A0, *B;
    MAP *map;
    INT i;
    size_t nnz, mem, mem_peak;
    VEC *x, *y0, *y1, *y2;
    double t0, t1, dnz, dnz1, mflops, mop;
    char *fn = "../test/cube.dat";
    FLOAT mem_max = 300;
    INT refine = 0;

    phgOptionsRegisterFilename("-mesh_file", "Mesh file", (char **)&fn);
    phgOptionsRegisterInt("-loop_count", "Loop count", &loop_count);
    phgOptionsRegisterInt("-refine", "Refinement level", &refine);
    phgOptionsRegisterFloat("-mem_max", "Maximum memory", &mem_max);

    phgInit(&argc, &argv);
    g = phgNewGrid(-1);
    if (!phgImport(g, fn, FALSE))
	phgError(1, "can't read file \"%s\".\n", fn);
    phgRefineAllElements(g, refine);
    u_h = phgDofNew(g, DOF_DEFAULT, 1, "u_h", DofNoAction);

    while (TRUE) {
	phgPrintf("\n");
	if (phgBalanceGrid(g, 1.2, 1, NULL, 0.))
	    phgPrintf("Repartition mesh, %d submeshes, load imbalance: %lg\n",
			g->nprocs, (double)g->lif);
	map = phgMapCreate(u_h, NULL);
	A = phgMapCreateMat(map, map);
	A->handle_bdry_eqns = TRUE;
	build_matrix(A, u_h);
	phgMatAssemble(A);

	/* Note: A is unsymmetric (A' != A) if boundary entries not removed */
	phgMatRemoveBoundaryEntries(A);

#if 0
	/* test block matrix operation */
	A0 = phgMatCreateBlockMatrix(g->comm, 1, 1, &A, NULL);
#else
	A0 = A;
#endif

	phgPrintf("%d DOF, %d elems, %d submeshes, matrix size: %d, LIF: %lg\n",
			DofGetDataCountGlobal(u_h), g->nleaf_global,
			g->nprocs, A->rmap->nglobal, (double)g->lif);

	/* test PHG mat-vec multiply */
	x = phgMapCreateVec(A->cmap, 1);
	y1 = phgMapCreateVec(A->rmap, 1);
	phgVecRandomize(x, 123);
	phgMatVec(MAT_OP_N, 1.0, A0, x, 0.0, &y1);

	phgPerfGetMflops(g, NULL, NULL);	/* reset flops counter */
	t0 = phgGetTime(NULL);
	for (i = 0; i < loop_count; i++) {
	    phgMatVec(MAT_OP_N, 1.0, A0, x, 0.0, &y1);
	}
	t1 = phgGetTime(NULL);
	mflops = phgPerfGetMflops(g, NULL, NULL);
	y0 = phgVecCopy(y1, NULL);
	nnz = A->nnz_d + A->nnz_o;
#if USE_MPI
	dnz1 = nnz;
	MPI_Reduce(&dnz1, &dnz, 1, MPI_DOUBLE, MPI_SUM, 0, g->comm);
#else
	dnz = nnz;
#endif
	mop = loop_count * (dnz + dnz - A->rmap->nlocal) * 1e-6;

	phgPrintf("\n");
	t1 -= t0;
	phgPrintf("   PHG:  time %0.4lf, nnz %0.16lg, %0.2lfMF (%0.2lfMF)\n",
			t1, dnz, mop / (t1 == 0 ? 1. : t1), mflops);

	/* test trans(A)*x */
	phgPerfGetMflops(g, NULL, NULL);	/* reset flops counter */
	t0 = phgGetTime(NULL);
	for (i = 0; i < loop_count; i++) {
	    phgMatVec(MAT_OP_T, 1.0, A0, x, 0.0, &y1);
	}
	t1 = phgGetTime(NULL);
	mflops = phgPerfGetMflops(g, NULL, NULL);
	t1 -= t0;
	phgPrintf("  A'*x:  time %0.4lf, nnz %0.16lg, %0.2lfMF (%0.2lfMF), "
		  "err: %le\n", t1, dnz, mop / (t1 == 0 ? 1. : t1), mflops,
		 (double)phgVecNorm2(phgVecAXPBY(-1.0, y0, 1.0, &y1), 0, NULL));

	/* time A * trans(A) */
	phgPerfGetMflops(g, NULL, NULL);	/* reset flops counter */
	t0 = phgGetTime(NULL);
	B = phgMatMat(MAT_OP_N, MAT_OP_N, 1.0, A, A, 0.0, NULL);
	t1 = phgGetTime(NULL);
	mflops = phgPerfGetMflops(g, NULL, NULL);
	nnz = B->nnz_d + B->nnz_o;
#if USE_MPI
	dnz1 = nnz;
	MPI_Reduce(&dnz1, &dnz, 1, MPI_DOUBLE, MPI_SUM, 0, g->comm);
#else
	dnz = nnz;
#endif
	/* compare B*x <--> A*A*x */
	y2 = phgMatVec(MAT_OP_N, 1.0, B, x, 0.0, NULL);
	phgMatVec(MAT_OP_N, 1.0, A0, y0, 0.0, &y1);
	phgMatDestroy(&B);
	t1 -= t0;
	phgPrintf("   A*A:  time %0.4lf, nnz %0.16lg, %0.2lfMF, err: %le\n",
		  t1, dnz, mflops,
		 (double)phgVecNorm2(phgVecAXPBY(-1.0, y1, 1.0, &y2), 0, NULL));

#if USE_PETSC
	{
	    Mat ma, mb;
	    MatInfo info;
	    Vec va, vb, vc;
	    PetscScalar *vec;

	    ma = phgPetscCreateMatAIJ(A);
	    MatGetVecs(ma, PETSC_NULL, &va);
	    VecDuplicate(va, &vb);
	    VecGetArray(va, &vec);
	    memcpy(vec, x->data, x->map->nlocal * sizeof(*vec));
	    VecRestoreArray(va, &vec);
	    MatMult(ma, va, vb);
	    phgPerfGetMflops(g, NULL, NULL);	/* reset flops counter */
	    t0 = phgGetTime(NULL);
	    for (i = 0; i < loop_count; i++) {
		MatMult(ma, va, vb);
	    }
	    t1 = phgGetTime(NULL);
	    mflops = phgPerfGetMflops(g, NULL, NULL);
	    VecGetArray(vb, &vec);
	    memcpy(y1->data, vec, x->map->nlocal * sizeof(*vec));
	    VecRestoreArray(vb, &vec);

	    MatGetInfo(ma, MAT_GLOBAL_SUM, &info);
	    /*phgPrintf("    --------------------------------------------"
		      "-------------------------\n");*/
	    phgPrintf("\n");
	    t1 -= t0;
	    dnz = info.nz_used;
	    phgPrintf(" PETSc:  time %0.4lf, nnz %0.16lg, %0.2lfMF (%0.2lfMF), "
		      "err: %le\n", t1, dnz, mop / (t1==0 ? 1.:t1), mflops,
		 (double)phgVecNorm2(phgVecAXPBY(-1.0, y0, 1.0, &y1), 0, NULL));

	    phgPerfGetMflops(g, NULL, NULL);	/* reset flops counter */
	    t0 = phgGetTime(NULL);
	    for (i = 0; i < loop_count; i++) {
		MatMultTranspose(ma, va, vb);
	    }
	    t1 = phgGetTime(NULL);
	    mflops = phgPerfGetMflops(g, NULL, NULL);
	    VecGetArray(vb, &vec);
	    memcpy(y1->data, vec, x->map->nlocal * sizeof(*vec));
	    VecRestoreArray(vb, &vec);
	    t1 -= t0;
	    phgPrintf("  A'*x:  time %0.4lf, nnz %0.16lg, %0.2lfMF (%0.2lfMF), "
		      "err: %le\n", t1, dnz, mop / (t1==0 ? 1.:t1), mflops,
		(double)phgVecNorm2(phgVecAXPBY(-1.0, y0, 1.0, &y1), 0, NULL));

	    phgPerfGetMflops(g, NULL, NULL);	/* reset flops counter */
	    t0 = phgGetTime(NULL);
	    MatMatMult(ma, ma, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &mb);
	    t1 = phgGetTime(NULL);
	    mflops = phgPerfGetMflops(g, NULL, NULL);
	    t1 -= t0;
	    MatGetInfo(mb, MAT_GLOBAL_SUM, &info);
	    dnz = info.nz_used;
	    VecDuplicate(va, &vc);
	    /* compare B*x <--> A*A*x */
	    MatMult(ma, vb, vc);
	    MatMult(mb, va, vb);
	    VecGetArray(vb, &vec);
	    memcpy(y1->data, vec, x->map->nlocal * sizeof(*vec));
	    VecRestoreArray(vb, &vec);
	    VecGetArray(vc, &vec);
	    memcpy(y2->data, vec, x->map->nlocal * sizeof(*vec));
	    VecRestoreArray(vc, &vec);
	    phgPrintf("   A*A:  time %0.4lf, nnz %0.16lg, %0.2lfMF, err: %le\n",
		  t1, dnz, mflops,
		 (double)phgVecNorm2(phgVecAXPBY(-1.0, y1, 1.0, &y2), 0, NULL));

	    phgPetscMatDestroy(&mb);
	    phgPetscMatDestroy(&ma);
	    phgPetscVecDestroy(&va);
	    phgPetscVecDestroy(&vb);
	    phgPetscVecDestroy(&vc);
	}
#endif	/* USE_PETSC */

#if USE_HYPRE
	{
	    HYPRE_IJMatrix ma;
	    HYPRE_IJVector va, vb, vc;
	    HYPRE_ParCSRMatrix  par_ma;
	    hypre_ParCSRMatrix  *par_mb;
	    HYPRE_ParVector	par_va, par_vb, par_vc;
	    HYPRE_Int offset, *ni, start, end;
	    assert(sizeof(INT)==sizeof(int) && sizeof(FLOAT)==sizeof(double));
	    setup_hypre_mat(A, &ma);
	    ni = phgAlloc(2 * A->rmap->nlocal * sizeof(*ni));
	    offset = A->cmap->partition[A->cmap->rank];
	    for (i = 0; i < A->rmap->nlocal; i++)
		ni[i] = i + offset;
	    HYPRE_IJVectorCreate(g->comm, offset, offset + A->rmap->nlocal - 1,
				 &va);
	    HYPRE_IJVectorCreate(g->comm, offset, offset + A->rmap->nlocal - 1,
				 &vb);
	    HYPRE_IJVectorCreate(g->comm, offset, offset + A->rmap->nlocal - 1,
				 &vc);
	    HYPRE_IJVectorSetObjectType(va, HYPRE_PARCSR);
	    HYPRE_IJVectorSetObjectType(vb, HYPRE_PARCSR);
	    HYPRE_IJVectorSetObjectType(vc, HYPRE_PARCSR);
	    HYPRE_IJVectorSetMaxOffProcElmts(va, 0);
	    HYPRE_IJVectorSetMaxOffProcElmts(vb, 0);
	    HYPRE_IJVectorSetMaxOffProcElmts(vc, 0);
	    HYPRE_IJVectorInitialize(va);
	    HYPRE_IJVectorInitialize(vb);
	    HYPRE_IJVectorInitialize(vc);
	    HYPRE_IJMatrixGetObject(ma, (void **)(void *)&par_ma);
	    HYPRE_IJVectorGetObject(va, (void **)(void *)&par_va);
	    HYPRE_IJVectorGetObject(vb, (void **)(void *)&par_vb);
	    HYPRE_IJVectorGetObject(vc, (void **)(void *)&par_vc);
	    HYPRE_IJVectorSetValues(va, A->cmap->nlocal, ni, (double *)x->data);
	    HYPRE_IJVectorAssemble(va);
	    HYPRE_IJVectorAssemble(vb);
	    HYPRE_IJVectorAssemble(vc);

	    HYPRE_IJMatrixGetRowCounts(ma, A->cmap->nlocal,
					ni, ni + A->rmap->nlocal);
	    for (i = 0, nnz = 0; i < A->rmap->nlocal; i++)
		nnz += ni[A->rmap->nlocal + i];
#if USE_MPI
	    dnz1 = nnz;
	    MPI_Reduce(&dnz1, &dnz, 1, MPI_DOUBLE, MPI_SUM, 0, g->comm);
#else
	    dnz = nnz;
#endif

	    HYPRE_ParCSRMatrixMatvec(1.0, par_ma, par_va, 0.0, par_vb);
	    phgPerfGetMflops(g, NULL, NULL);	/* reset flops counter */
	    t0 = phgGetTime(NULL);
	    for (i = 0; i < loop_count; i++) {
		HYPRE_ParCSRMatrixMatvec(1.0, par_ma, par_va, 0.0, par_vb);
	    }
	    t1 = phgGetTime(NULL);
	    mflops = phgPerfGetMflops(g, NULL, NULL);
	    HYPRE_IJVectorGetValues(vb, A->rmap->nlocal, ni, (double*)y1->data);
	    /*phgPrintf("    --------------------------------------------"
		      "-------------------------\n");*/
	    phgPrintf("\n");
	    t1 -= t0;
	    phgPrintf(" HYPRE:  time %0.4lf, nnz %0.16lg, %0.2lfMF (%0.2lfMF), "
		      "err: %le\n", t1, dnz, mop / (t1==0 ? 1.:t1), mflops,
		(double)phgVecNorm2(phgVecAXPBY(-1.0, y0, 1.0, &y1), 0, NULL));

	    phgPerfGetMflops(g, NULL, NULL);	/* reset flops counter */
	    t0 = phgGetTime(NULL);
	    for (i = 0; i < loop_count; i++) {
		HYPRE_ParCSRMatrixMatvecT(1.0, par_ma, par_va, 0.0, par_vb);
	    }
	    t1 = phgGetTime(NULL);
	    mflops = phgPerfGetMflops(g, NULL, NULL);
	    HYPRE_IJVectorGetValues(vb, A->rmap->nlocal, ni, (double*)y1->data);
	    t1 -= t0;
	    phgPrintf("  A'*x:  time %0.4lf, nnz %0.16lg, %0.2lfMF (%0.2lfMF), "
		      "err: %le\n", t1, dnz, mop / (t1==0 ? 1.:t1), mflops,
		(double)phgVecNorm2(phgVecAXPBY(-1.0, y0, 1.0, &y1), 0, NULL));

	    phgPerfGetMflops(g, NULL, NULL);	/* reset flops counter */
	    t0 = phgGetTime(NULL);
	    /* Note: 'HYPRE_ParCSRMatrix' is currently typedef'ed to
	     *	     'hypre_ParCSRMatrix *' */
	    par_mb = hypre_ParMatmul((hypre_ParCSRMatrix *)par_ma,
					(hypre_ParCSRMatrix *)par_ma);
	    t1 = phgGetTime(NULL);
	    mflops = phgPerfGetMflops(g, NULL, NULL);
	    start = hypre_ParCSRMatrixFirstRowIndex(par_mb);
	    end = hypre_ParCSRMatrixLastRowIndex(par_mb) + 1;
	    for (i = start, nnz = 0; i < end; i++) {
		HYPRE_Int ncols;
		hypre_ParCSRMatrixGetRow(par_mb, i, &ncols, NULL, NULL);
		hypre_ParCSRMatrixRestoreRow(par_mb, i, &ncols, NULL, NULL);
		nnz += ncols;
	    }
#if USE_MPI
	    dnz1 = nnz;
	    MPI_Reduce(&dnz1, &dnz, 1, MPI_DOUBLE, MPI_SUM, 0, g->comm);
#else
	    dnz = nnz;
#endif
	    /* compare B*x <--> A*A*x */
	    HYPRE_ParCSRMatrixMatvec(1.0, par_ma, par_vb, 0.0, par_vc);
	    HYPRE_ParCSRMatrixMatvec(1.0, (void *)par_mb, par_va, 0.0, par_vb);
	    HYPRE_IJVectorGetValues(vb, A->rmap->nlocal, ni, (double*)y1->data);
	    HYPRE_IJVectorGetValues(vc, A->rmap->nlocal, ni, (double*)y2->data);
	    hypre_ParCSRMatrixDestroy((par_mb));
	    t1 -= t0;
	    phgPrintf("   A*A:  time %0.4lf, nnz %0.16lg, %0.2lfMF, err: %le\n",
		  t1, dnz, mflops,
		 (double)phgVecNorm2(phgVecAXPBY(-1.0, y1, 1.0, &y2), 0, NULL));

	    phgFree(ni);
	    HYPRE_IJMatrixDestroy(ma);
	    HYPRE_IJVectorDestroy(va);
	    HYPRE_IJVectorDestroy(vb);
	    HYPRE_IJVectorDestroy(vc);
	}
#endif	/* USE_HYPRE */

	if (A0 != A)
	    phgMatDestroy(&A0);
#if 0
if (A->rmap->nglobal > 1000) {
    VEC *v = phgMapCreateVec(A->rmap, 3);
    for (i = 0; i < v->map->nlocal; i++) {
	v->data[i + 0 * v->map->nlocal] = 1 * (i + v->map->partition[g->rank]);
	v->data[i + 1 * v->map->nlocal] = 2 * (i + v->map->partition[g->rank]);
	v->data[i + 2 * v->map->nlocal] = 3 * (i + v->map->partition[g->rank]);
    }
    phgMatDumpMATLAB(A, "A", "A.m");
    phgVecDumpMATLAB(v, "v", "v.m");
    phgFinalize();
    exit(0);
}
#endif
	phgMatDestroy(&A);
	phgVecDestroy(&x);
	phgVecDestroy(&y0);
	phgVecDestroy(&y1);
	phgVecDestroy(&y2);
	phgMapDestroy(&map);
	mem = phgMemoryUsage(g, &mem_peak);
	dnz = mem / (1024.0 * 1024.0);
	dnz1 = mem_peak / (1024.0 * 1024.0);
	/*phgPrintf("    --------------------------------------------"
		  "-------------------------\n");*/
	phgPrintf("\n");
	phgPrintf("  Memory: current %0.4lgMB, peak %0.4lgMB\n", dnz, dnz1);
#if 0
{
    static int loop_count = 0;
    if (++loop_count == 4)
	break;
}
#endif
	if (mem_peak > 1024 * (size_t)1024 * mem_max)
	    break;
	phgRefineAllElements(g, 1);
    }
    phgDofFree(&u_h);
    phgFreeGrid(&g);
    phgFinalize();

    return 0;
}
Esempio n. 10
0
int
main(int argc, char *argv[])
{
    GRID *g;
    DOF *u, *v, *w, *u0, *v0, *w0;
    SOLVER *solver;
    INT i, j;
    char *fn = "cube.dat";

    phgVerbosity = 0;
    phgInit(&argc, &argv);
    /*phgPause(0);*/
    g = phgNewGrid(-1);
    if (!phgImport(g, fn, FALSE))
	phgError(1, "can't read file \"%s\".\n", fn);

    for (i = 0; i < 4; i++)
	phgRefineAllElements(g, 1);
    phgBalanceGrid(g, 1.0, 0, NULL, 0.);
    for (i = 0; i < 8; i++) {
	phgRefineRandomElements(g, "25%");
	phgBalanceGrid(g, 1.2, -1, NULL, 0.);
    }
    phgCheckConformity(g);

    u = phgDofNew(g, DOF_P1,  1, "u", DofNoAction);
    v = phgDofNew(g, DOF_ND1, 1, "v", DofNoAction);
    w = phgDofNew(g, DOF_P1,  1, "w", DofNoAction);

    phgDofSetDataByValue(u, 0.0);
    phgDofSetDataByValue(v, 0.0);
    phgDofSetDataByValue(w, 0.0);

    u0 = phgDofNew(g, u->type, u->dim, "u0", DofNoAction);
    v0 = phgDofNew(g, v->type, v->dim, "v0", DofNoAction);
    w0 = phgDofNew(g, w->type, w->dim, "w0", DofNoAction);

    solver = phgSolverCreate(SOLVER_DEFAULT, u, v, w, NULL);

    for (i = 0; i < DofGetDataCount(u); i++) {
	j = phgSolverMapD2L(solver, 0, i);
	u0->data[i] = (FLOAT)(phgSolverMapL2G(solver, j) % 3);
	phgSolverAddMatrixEntry(solver, j, j, 1.0);
	phgSolverAddRHSEntry(solver, j, u0->data[i]);
    }

    for (i = 0; i < DofGetDataCount(v); i++) {
	j = phgSolverMapD2L(solver, 1, i);
	v0->data[i] = (FLOAT)(phgSolverMapL2G(solver, j) % 5);
	phgSolverAddMatrixEntry(solver, j, j, 1.0);
	phgSolverAddRHSEntry(solver, j, v0->data[i]);
    }

    for (i = 0; i < DofGetDataCount(w); i++) {
	j = phgSolverMapD2L(solver, 2, i);
	w0->data[i] = (FLOAT)(phgSolverMapL2G(solver, j) % 7);
	phgSolverAddMatrixEntry(solver, j, j, 1.0);
	phgSolverAddRHSEntry(solver, j, w0->data[i]);
    }

    phgSolverSolve(solver, TRUE, u, v, w, NULL);
    phgSolverDestroy(&solver);

    phgDofAXPY(-1.0, u0, &u);
    phgDofAXPY(-1.0, v0, &v);
    phgDofAXPY(-1.0, w0, &w);
    phgPrintf("Error: u = %lg, v = %lg, w = %lg\n",
		(double)phgDofNormInftyVec(u),
		(double)phgDofNormInftyVec(v),
		(double)phgDofNormInftyVec(w));

    phgDofFree(&u);
    phgDofFree(&v);
    phgDofFree(&w);
    phgDofFree(&u0);
    phgDofFree(&v0);
    phgDofFree(&w0);
    phgFreeGrid(&g);
    phgFinalize();
    return 0;
}
Esempio n. 11
0
void
phgNSBuildPc(NSSolver *ns)
{
    GRID *g = ns->g;
    SIMPLEX *e;
    FLOAT *dt = ns->dt;
    int i, j, q, s, k, l;
    FLOAT Theta = _nsp->Theta, nu = _nsp->nu, Thet1, nu0 = 0;
    DOF *tmp_u1 = phgDofNew(g, _nsp->utype, Dim, "tmp u1", func_u);
    int viscosity_type = ns->viscosity_type;
    LTYPE ltype = ns->ltype;


#if STEADY_STATE
    assert(fabs(Theta - 1) < 1e-12);
    Thet1 = 0; Unused(Thet1);
    Unused(dt);
#else
    Thet1 = 1 - Theta;
#endif /* STEADY_STATE */


    ForAllElements(g, e) {
	int M = ns->u[1]->type->nbas;	/* num of bases of Velocity */
	int N = ns->p[1]->type->nbas;	/* num of bases of Pressure */
	int order = 2 * DofTypeOrder(ns->p[1], e) + 
	    DofTypeOrder(ns->u[1], e) - 1; 	/* highest order term (u \nabla p, psi)  */
	FLOAT Ap[N][N], Fp[N][N], Qp[N][N], bufp[N], rhs1 = 1;
	FLOAT F[M*Dim][M*Dim], B[N][M*Dim], Bt[M*Dim][N];
	INT Ip[N];
	QUAD *quad;
	FLOAT vol, det;
	const FLOAT *w, *p, *vw, *gu, *vTe;

	quad = phgQuadGetQuad3D(order);
	vw = phgQuadGetDofValues(e, ns->wind, quad);  /* value wind */
	gu = phgQuadGetDofValues(e, ns->gradu[1], quad);        /* grad u^{n+1} */
	if (ns_params->noniter_temp)
	    vTe = phgQuadGetDofValues(e, ns->T[1], quad);  /* value temp */
	else
	    vTe = phgQuadGetDofValues(e, ns->T[0], quad);  /* value temp */
	
	vol = 0;
	Bzero(Ap); Bzero(Fp); Bzero(Qp); 
	Bzero(F); Bzero(Bt); Bzero(B);
	Bzero(bufp); 

	p = quad->points;
	w = quad->weights;
	for (q = 0; q < quad->npoints; q++) {
	    phgGeomGetCurvedJacobianAtLambda(g, e, p, &det);
	    vol = fabs(det / 6.);

	    for (i = 0; i < N; i++) {
		const FLOAT *gi = phgQuadGetBasisValues(e, ns->p[1], i, quad) + q;       /* phi_i */
		const FLOAT *ggi = phgQuadGetBasisCurvedGradient(e, ns->p[1], i, quad, q);    /* grad phi_i */
		for (j = 0; j < N; j++) {
		    const FLOAT *gj = phgQuadGetBasisValues(e, ns->p[1], j, quad) + q;       /* phi_j */
		    const FLOAT *ggj = phgQuadGetBasisCurvedGradient(e, ns->p[1], j, quad, q);    /* grad phi_i */
		    
		    nu = get_effective_viscosity(gu, *vTe, 0, viscosity_type);
		    if (i == 0 && j == 0)
			nu0 += nu;
#if ICE_BENCH_TEST ||				\
    ESIMINT_TEST ||				\
    HEINO_TEST ||				\
    TEST_CASE == ICE_EXACT	||		\
    TEST_CASE == ICE_GREEN_LAND
		    Unused(dt);
		    /* Note: B Q^-1 Bt ~ Ap(nu=1),
		     *       Fp(nu varies) is very different to Ap */
		    Ap[i][j] += vol*(*w) * INNER_PRODUCT(ggj, ggi);
#  if USE_QP_ONLY

		    //Qp[i][j] += vol*(*w) * LEN_SCALING * PRES_SCALING /(nu) * (*gj) * (*gi);
		    Qp[i][j] += vol*(*w) * 1. /(EQU_SCALING * nu) * (*gj) * (*gi);
		    /* if (i < NVert && j < NVert) { */
		    /* 	Qp[i][j] += vol*(*w) * LEN_SCALING * PRES_SCALING / (nu) * (*gj) * (*gi); */
		    /* } else if (i == NVert && j == NVert) { */
		    /* 	Qp[i][j] += vol*(*w) * LEN_SCALING * PRES_SCALING / (nu) * (*gj) * (*gi); */
		    /* } */

#  else
		    Qp[i][j] += vol*(*w) * (*gj) * (*gi);
#  endif
		    Fp[i][j] += vol*(*w) * (EQU_SCALING * nu * INNER_PRODUCT(ggj, ggi)
					    );
#elif STEADY_STATE 
		    Ap[i][j] += vol*(*w) * INNER_PRODUCT(ggj, ggi);
		    Qp[i][j] += vol*(*w) * (*gj) * (*gi);
		    Fp[i][j] += vol*(*w) * (nu * INNER_PRODUCT(ggj, ggi) * EQU_SCALING
					    );
#elif TIME_DEP_NON
		    Ap[i][j] += vol*(*w) * INNER_PRODUCT(ggj, ggi);
		    Qp[i][j] += vol*(*w) * (*gj) * (*gi);
		    Fp[i][j] += vol*(*w) * ((*gj) * (*gi) / dt[0]
					    + Theta * (nu * INNER_PRODUCT(ggj, ggi)
						       )
					    );
#else
		    TIME_DEP_LINEAR_ENTRY; /* Unavailable */
#endif /* STEADY_STATE */
		}
	    }

	    vw += Dim; 
	    gu += DDim;
	    vTe++;
	    w++; p += Dim+1;
	}


	/* Map: Element -> system */
	for (i = 0; i < N; i++) 
	    Ip[i] = phgMapE2L(_pcd->matFp->cmap, 0, e, i);

	/*
	 * PCD boundary setup I:
	 * Automaticly decide inflow boundary condition using wind direction.
	 *
	 * NOT active.
	 * */
	if (FALSE && !_nsp->pin_node) {
	    for (i = 0; i < N; i++) {
		BOOLEAN flag_inflow = FALSE;
		for (s = 0; s < NFace; s++) {
		    SHORT bases[NbasFace(ns->p[1])];
		    FLOAT *coord, vw_[3]; 
		    const FLOAT *lam, *normal;

		    if (!(e->bound_type[s] & BDRY_MASK))
			//if (!(e->bound_type[s] & INFLOW))
			continue;	/* boundary face */

		    phgDofGetBasesOnFace(ns->p[1], e, s, bases);
		    for (j = 0; j < NbasFace(ns->p[1]); j++) 
			if (i == bases[j]) {
			    normal = phgGeomGetFaceOutNormal(g, e, s);
			    coord = phgDofGetElementCoordinates(ns->p[1], e, i);
			    lam = phgGeomXYZ2Lambda(g, e, coord[0], coord[1], coord[2]);
			    phgDofEval(tmp_u1, e, lam, vw_);
			    if (INNER_PRODUCT(vw_, normal) > 1e-8) 
				flag_inflow = TRUE;
			}
		}
		
		if (flag_inflow) {
		    Bzero(bufp); bufp[i] = 1.0;
		    phgMatAddEntries(_pcd->matAp, 1, Ip + i, N, Ip, bufp);
		    phgMatAddEntries(_pcd->matFp, 1, Ip + i, N, Ip, bufp);
		    //phgMatAddEntries(_pcd->matQp, 1, Ip + i, N, Ip, bufp);
		    phgVecAddEntries(_pcd->rhsScale, 0, 1, Ip + i, &rhs1);
		}
		else {
		    /* interior node Or Neumann */
		    phgMatAddEntries(_pcd->matAp, 1, Ip + i, N, Ip, Ap[i]);
		    phgMatAddEntries(_pcd->matFp, 1, Ip + i, N, Ip, Fp[i]);
		    //phgMatAddEntries(_pcd->matQp, 1, Ip + i, N, Ip, Qp[i]);
		}
		phgMatAddEntries(_pcd->matQp, 1, Ip + i, N, Ip, Qp[i]);
	    }
	} 
	/*
	 * PCD boundary setup II:
	 * Enclose flow: use pinnode boundary.
	 *
	 * Qp is pinned, this is different to open flow.
	 * 
	 * */
	else if (_nsp->pin_node) {

	    for (i = 0; i < N; i++) {
		if (phgDofDirichletBC(_pcd->pbc, e, i, NULL, bufp, NULL, DOF_PROJ_NONE)) {
#if PIN_AT_ROOT 
		    if (g->rank != 0)
		    	phgError(1, "Pinned node only on rank 0!\n");
		    if (e->verts[i] != ns->pinned_node_id)
			phgError(1, "pinned node [%d] & [%d] doesn't coincide when build pc!\n",
				 e->verts[i], ns->pinned_node_id);
#else
		    if (GlobalVertex(g, e->verts[i]) != ns->pinned_node_id)
			phgError(1, "pinned node [%d] & [%d] doesn't coincide when build pc!\n",
				 e->verts[i], ns->pinned_node_id);
#endif /* PIN_AT_ROOT */

		    phgMatAddEntries(_pcd->matAp, 1, Ip + i, N, Ip, bufp);
		    phgMatAddEntries(_pcd->matFp, 1, Ip + i, N, Ip, bufp);
		    phgMatAddEntries(_pcd->matQp, 1, Ip + i, N, Ip, bufp);
		    phgVecAddEntries(_pcd->rhsScale, 0, 1, Ip + i, &rhs1);
		} else {
		    /* interior node Or Neumann */
		    phgMatAddEntries(_pcd->matAp, 1, Ip + i, N, Ip, Ap[i]);
		    phgMatAddEntries(_pcd->matFp, 1, Ip + i, N, Ip, Fp[i]);
		    phgMatAddEntries(_pcd->matQp, 1, Ip + i, N, Ip, Qp[i]);
		}
	    }
	}
	/*
	 * PCD boundary setup III:
	 * Open flow: there could be varies kinds of combination on seting up
	 *   boundary conditon, but Inflow:Robin & Outflow:scaled Dirich is
	 *   prefered. See Ref[2].
	 * 
	 * */
	else {
	    for (i = 0; i < N; i++) {

		/*****************/
                /* Inflow	 */
                /*****************/
#warning PCD B.C.: Step 2.1. build mat, all neumann, add dirich entries
		if (FALSE && phgDofDirichletBC(_pcd->dof_inflow, e, i, NULL, bufp, NULL, DOF_PROJ_NONE)) {
		    phgMatAddEntries(_pcd->matAp, 1, Ip + i, N, Ip, bufp);
		    phgMatAddEntries(_pcd->matFp, 1, Ip + i, N, Ip, bufp);
		    phgMatAddEntries(_pcd->matQp, 1, Ip + i, N, Ip, bufp);
		    phgVecAddEntries(_pcd->rhsScale, 0, 1, Ip + i, &rhs1);
		} else if (FALSE && phgDofDirichletBC(_pcd->dof_outflow, e, i, NULL, bufp, NULL, DOF_PROJ_NONE)
			   && !(phgDofGetElementBoundaryType(ns->p[1], e, i) & INFLOW) ) {

		    ERROR_MSG("Fp, Qp");
		    nu = get_effective_viscosity(NULL, 0, 0, viscosity_type);
		    phgMatAddEntries(_pcd->matAp, 1, Ip + i, N, Ip, bufp);
		    bufp[i] *= EQU_SCALING * nu;
		    phgMatAddEntries(_pcd->matFp, 1, Ip + i, N, Ip, bufp);
		    phgVecAddEntries(_pcd->rhsScale, 0, 1, Ip + i, &rhs1);

		    //phgMatAddEntries(_pcd->matQp, 1, Ip + i, N, Ip, bufp);
		} else if (FALSE && phgDofDirichletBC(_pcd->pbc, e, i, NULL, bufp, NULL, DOF_PROJ_NONE)) {
		    phgMatAddEntries(_pcd->matAp, 1, Ip + i, N, Ip, bufp);
		    phgMatAddEntries(_pcd->matFp, 1, Ip + i, N, Ip, bufp);
		    phgMatAddEntries(_pcd->matQp, 1, Ip + i, N, Ip, bufp);
		    phgVecAddEntries(_pcd->rhsScale, 0, 1, Ip + i, &rhs1);
		}
		else if (FALSE) {
		    /* interior node Or Neumann */

		    ERROR_MSG("Fp, Qp");
		    phgMatAddEntries(_pcd->matAp, 1, Ip + i, N, Ip, Ap[i]);
		    phgMatAddEntries(_pcd->matFp, 1, Ip + i, N, Ip, Fp[i]);
		    //phgMatAddEntries(_pcd->matQp, 1, Ip + i, N, Ip, Qp[i]);
		}

		/******************/
                /* No bdry	  */
                /******************/
		//phgMatAddEntries(_pcd->matFp, 1, Ip + i, N, Ip, Fp[i]);
		phgMatAddEntries(_pcd->matQp, 1, Ip + i, N, Ip, Qp[i]);
	    }
	}


	if (0) {
	    /* Special term <[[p_i]], [[p_j]]> */
	    int face;
	    nu0 /= quad->npoints;
	    for (face = 0; face < NFace; face++) {
		FLOAT area =  phgGeomGetFaceArea(g, e, face);
		//FLOAT value = {area, -area};
		FLOAT values[2] = {vol * 1. /(EQU_SCALING * nu0),
				   -vol * 1. /(EQU_SCALING * nu0)};
		SIMPLEX *e_neigh;

		phgMatAddEntries(_pcd->matQp, 1, Ip+NVert, 1, Ip+NVert, values);
		if ((e_neigh = GetNeighbour(e, face)) != NULL) {
		    INT Ip_neigh = phgMapE2L(_pcd->matFp->cmap, 0, e_neigh, NVert);
		    phgMatAddEntries(_pcd->matQp, 1, Ip+NVert, 1, &Ip_neigh, values + 1);
		}
	    }
	}

    }	/* end element */
Esempio n. 12
0
void phgNSInitPc(NSSolver *ns)
{
    GRID *g = ns->g;
    MAP *Pmap = ns->Pmap, *Pbcmap;
    BOOLEAN use_Fu = _nsp->use_Fu;
    int verb;

    /* pcd boundary type test */
    _pcd->dof_inflow = phgDofNew(g, _nsp->ptype, 1, "dof inflow", DofNoAction);
    _pcd->dof_outflow = phgDofNew(g, _nsp->ptype, 1, "dof outflow", DofNoAction);
    _pcd->dof_nobdry = phgDofNew(g, _nsp->ptype, 1, "dof nobdry", DofNoAction);

    phgDofSetDirichletBoundaryMask(_pcd->dof_inflow, INFLOW);
    phgDofSetDirichletBoundaryMask(_pcd->dof_outflow, OUTFLOW);
    phgDofSetDirichletBoundaryMask(_pcd->dof_nobdry, 0);

    _pcd->map_inflow = phgMapCreate(_pcd->dof_inflow, NULL);
    _pcd->map_outflow = phgMapCreate(_pcd->dof_outflow, NULL);
    _pcd->map_nobdry = phgMapCreate(_pcd->dof_nobdry, NULL);

    _pcd->Pbcmap = phgMapCreate(_pcd->pbc, NULL);
    Pbcmap = _pcd->Pbcmap;

    Unused(Pmap);
#warning PCD B.C.: step 1. build mat using map... 
    /*
     * PCD boundary setup: should be consistent with code above
     */
    if (_nsp->pin_node) {
	_pcd->matFp = phgMapCreateMat(Pbcmap, Pbcmap);
	_pcd->matAp = phgMapCreateMat(Pbcmap, Pbcmap);
	_pcd->matQp = phgMapCreateMat(Pbcmap, Pbcmap);
    } else {
	//_pcd->matAp = phgMapCreateMat(_pcd->map_inflow, _pcd->map_inflow);
	//_pcd->matFp = phgMapCreateMat(_pcd->map_inflow, _pcd->map_inflow);
	_pcd->matFp = phgMapCreateMat(_pcd->map_outflow, _pcd->map_outflow);
	_pcd->matAp = phgMapCreateMat(_pcd->map_outflow, _pcd->map_outflow);
	//_pcd->matQp = phgMapCreateMat(_pcd->map_outflow, _pcd->map_outflow);
	//_pcd->matQp = phgMapCreateMat(_pcd->map_inflow, _pcd->map_inflow);
	//_pcd->matFp = phgMapCreateMat(_pcd->map_nobdry, _pcd->map_nobdry);
	//_pcd->matAp = phgMapCreateMat(_pcd->map_nobdry, _pcd->map_nobdry);
	//_pcd->matFp = phgMapCreateMat(_pcd->map_nobdry, _pcd->map_nobdry);
	_pcd->matQp = phgMapCreateMat(_pcd->map_nobdry, _pcd->map_nobdry);
    }

    /* stokes problem: get SYMETRIC mat when assemble.
     * Handle_bdry_eqns means mat is composed with row of boundary row
     * and non-bdry row, and eliminating mat columes of dirichlet dof. 
     */
    if (_nsp->use_symetric) {
	_pcd->matFp->handle_bdry_eqns = TRUE;
	_pcd->matAp->handle_bdry_eqns = TRUE;
	_pcd->matQp->handle_bdry_eqns = TRUE;
    } 
    /* genearl NS: no need to eliminate mat columes of dirichlet dof */
    else {
	_pcd->matFp->handle_bdry_eqns = FALSE;
	_pcd->matAp->handle_bdry_eqns = FALSE;
	_pcd->matQp->handle_bdry_eqns = FALSE;
    }	
    
    _pcd->rhsScale = phgMapCreateVec(_pcd->matQp->rmap, 1);
    phgVecDisassemble(_pcd->rhsScale);

    ns->pc = phgMat2Solver(SOLVER_PreOnly, ns->solver_u->mat);
    if (_nsp->use_PCD)
	phgSolverSetPC(ns->solver_u, ns->pc, pc_proc);

    /* solver F */
    phgOptionsPush();
    phgOptionsSetOptions("-solver hypre "
			 "-hypre_solver pcg "
			 "-hypre_pc boomeramg "
			 "-solver_maxit 10 "
			 "-solver_rtol 1e-4");
    phgOptionsSetOptions(_nsp->F_opts);
    /* use matF in the preconditioning matrix */
    _pcd->solver_F = phgMat2Solver(SOLVER_DEFAULT, ns->matF);
    _pcd->solver_F->verb = SUB_SOLVER_VERB; /* Set user options. */
    _pcd->pc_F = NULL;
#if USE_MG 
    if (ns_params->use_mg_F) {
	MAT *matF = ns->matF;

	assert(ns_params->use_PCD && !ns_params->use_Fu);
	_pcd->pc_F = phgMat2Solver(SOLVER_PreOnly, matF);
	phgOptionsSetOptions("-solver petsc ");
	matF->mv_data = phgAlloc(sizeof(*matF->mv_data));
	matF->mv_data[0] = (void *) ns->mg;
	phgSolverSetPC(_pcd->solver_F, _pcd->pc_F, mg_pc_proc);
    }
#endif /* USE_MG */
    _pcd->solver_F->warn_maxit = FALSE;
    phgOptionsPop();

    /* solver Ap */
    phgOptionsPush();
    phgOptionsSetOptions("-solver hypre "
			 "-hypre_solver gmres "
			 "-hypre_pc boomeramg "
			 "-solver_maxit 10 "
			 "-solver_rtol 1e-3");
    phgOptionsSetOptions(_nsp->Ap_opts);
    _pcd->solver_Ap = phgMat2Solver(SOLVER_DEFAULT, _pcd->matAp);
    _pcd->solver_Ap->warn_maxit = FALSE;
    _pcd->solver_Ap->verb = SUB_SOLVER_VERB;
    phgOptionsPop();
    _pcd->pc_Ap = NULL;
#if USE_MG 
    if (ns_params->use_mg_Ap) {
	MAT *matAp = _pcd->matAp;

	assert(ns_params->use_PCD);
	_pcd->pc_Ap = phgMat2Solver(SOLVER_PreOnly, matAp);
	phgOptionsSetOptions("-solver petsc ");
	matAp->mv_data = phgAlloc(sizeof(*matAp->mv_data));
	matAp->mv_data[0] = (void *) ns->mg;
	phgSolverSetPC(_pcd->solver_Ap, _pcd->pc_Ap, mg_pc_proc);
    }
#endif /* USE_MG */


    /* solver Qp */
    phgOptionsPush();
    phgOptionsSetOptions("-solver hypre "
			 "-hypre_solver pcg "
			 "-hypre_pc boomeramg "
			 "-solver_maxit 10 "
			 "-solver_rtol 1e-3");
    phgOptionsSetOptions(_nsp->Qp_opts);
    _pcd->solver_Qp = phgMat2Solver(SOLVER_DEFAULT, _pcd->matQp);
    _pcd->solver_Qp->warn_maxit = FALSE;
    _pcd->solver_Qp->verb = SUB_SOLVER_VERB;
    phgOptionsPop();
    _pcd->pc_Qp = NULL;
#if USE_MG 
    if (ns_params->use_mg_Qp) {
	MAT *matQp = _pcd->matQp;

	assert(ns_params->use_PCD);
	_pcd->pc_Qp = phgMat2Solver(SOLVER_PreOnly, matQp);
	phgOptionsSetOptions("-solver petsc ");
	matQp->mv_data = phgAlloc(sizeof(*matQp->mv_data));
	matQp->mv_data[0] = (void *) ns->mg;
	phgSolverSetPC(_pcd->solver_Qp, _pcd->pc_Qp, mg_pc_proc);
    }
#endif /* USE_MG */

    /* Fu for solve F^{-1} */
    if (use_Fu) { /* _nsp->implicit_centrip &&  */
	DOF *u1;
	MAP *u1map;
	MAT *matFu;
	u1 = _pcd->u1 = 
	    phgDofNew(g, _nsp->utype, 1, "velocity component u", DofNoAction);
	phgDofSetDirichletBoundaryMask(u1, SETFLOW);
	
	u1map = _pcd->u1map
	    = phgMapCreate(_pcd->u1, NULL);
	matFu = _pcd->matFu 
	    = phgMapCreateMat(u1map, u1map);
	if (_nsp->use_symetric)
	    matFu->handle_bdry_eqns = TRUE;

	/* solver Fu */
	phgOptionsPush();
	phgOptionsSetOptions("-solver hypre "
			     "-hypre_solver pcg "
			     "-hypre_pc boomeramg "
			     "-solver_maxit 10 "
			     "-solver_rtol 1e-4");
	phgOptionsSetOptions(_nsp->Fu_opts);
	_pcd->solver_Fu = phgMat2Solver(SOLVER_DEFAULT, _pcd->matFu);
	_pcd->solver_Fu->warn_maxit = FALSE;
	_pcd->solver_Fu->verb = SUB_SOLVER_VERB;
	phgOptionsPop();

    }

    return;
}