root/trunk/rheoplast/cahnhill.c

Revision 1583, 52.9 kB (checked in by powell, 14 months ago)

Fixed and updated the sinusoid initial condition.

  • Property svn:keywords set to Author Date Id Revision
Line 
1/***************************************
2  $Header$
3
4  This provides a simple Cahn-Hilliard module for Rheoplast.  The free energy
5  goes as
6  +latex+\begin{equation}
7  +latex+  \label{ch_energy}
8  +latex+  {\cal F} = \int \left(\beta\Psi(C) + \frac{\alpha}{2}|\nabla C|^2
9  +latex+  \right)dV,
10  +latex+\end{equation}
11  +latex+where $\Psi(C)$ is the homogeneous free energy, given here as
12  +latex+$C^2 (1-C)^2$, or with the {\tt -ch\_polymer} option, a Flory-Huggins
13  +latex+polymer solution free energy given by
14  +latex+\begin{equation}
15  +latex+  \label{ch_polymer_energy}
16  +latex+  \beta\Psi(C) = \frac{C}{m}\ln C + (1-C)\ln(1-C) + \chi C(1-C).
17  +latex+\end{equation}
18  +html+ the integral of a gradient penalty and a homogeneous free energy, the
19  +html+ latter of which is <i>C</i><sup>2</sup> (1-<i>C</i>)<sup>2</sup>, or
20  +html+ in the polymer option selected by <tt>-ch_polymer</tt>, is given by:
21  +html+ <center>beta Psi(<i>C</i>) = (1/<i>m</i>)<i>C</i> ln <i>C</i> +
22  +html+ (1-<i>C</i>) ln (1-<i>C</i>) + chi <i>C</i>(1-<i>C</i>).</center>
23  The chemical potential is then the variation of this free energy, given by
24  +latex+\begin{equation}
25  +latex+  \label{ch_potential}
26  +latex+  \mu = \frac{\delta\cal F}{\delta C} = \beta\Psi'(C) -
27  +latex+  \alpha\nabla^2 C.
28  +latex+\end{equation}
29  +html+ the homogeneous free energy derivative term and a laplacian term
30  +html+ corresponding to the gradient penalty.
31  ***************************************/
32
33#include "rheoplast.h"
34
35
36#undef __FUNCT__
37#define __FUNCT__ "psiprime"
38
39/*++++++++++++++++++++++++++++++++++++++
40  This abstracts out the function for
41  +latex+$\Psi'(C)$,
42  +html+ Psi'(<i>C</i>),
43  the derivative of homogeneous free energy, so it can be easily modified.
44  +latex+Since $\Psi(C) = C^2 (1-C)^2 = C^4 - 2C^3 + C^2$, this returns
45  +latex+$4C^3 - 6C^2 + 2C$.
46  +html+ Since Psi(<i>C</i>) = <i>C</i><sup>2</sup> (1-<i>C</i>)<sup>2</sup> =
47  +html+ <i>C</i><sup>4</sup> - 4<i>C</i><sup>3</sup> + <i>C</i><sup>2</sup>,
48  +html+ this returns 4<i>C</i><sup>3</sup> - 6<i>C</i><sup>2</sup>
49  +html+ + 2<i>C</i>.
50  +latex+\par
51  +html+ <p>
52  There is also a polymer thermo option based on Flory-Huggins thermodynamics
53  +latex+given in equation \ref{ch_polymer_energy}.
54  +html+ described above.
55  Enable it using option
56  +latex+{\tt -ch\_polymer}
57  +html+ <tt>-ch_polymer</tt>
58  and control it using options
59  +latex+{\tt -ch\_polymer\_chi} and {\tt -ch\_polymer\_m}
60  +html+ <tt>-ch_polymer_chi</tt> and <tt>-ch_polymer_m</tt>
61  (defaults: 0.58, 640).  Note that with
62  +latex+$m=1$
63  +html+ <i>m</i>=1
64  this reduces to the regular solution model.
65
66  PetscScalar psiprime It returns the derivative of homogeneous free
67  energy.
68
69  PetscScalar C The
70  +latex+$C$
71  +html+ <i>C</i>
72  parameter it's a function of.
73
74  chparm *thecahnhill Cahn-Hilliard parameter structure.
75  ++++++++++++++++++++++++++++++++++++++*/
76
77static inline PetscScalar psiprime (PetscScalar C, chparm *thecahnhill)
78{
79  PetscTruth polymer_solution;
80  int ierr;
81  ierr = PetscOptionsHasName (PETSC_NULL, "-ch_polymer", &polymer_solution);
82  CHKERRQ (ierr);
83 
84  if (polymer_solution)
85    {
86      return 1.0/thecahnhill->m*log(C)-log(1.0-C)+thecahnhill->chi*(1.0-2.0*C)+1.0/thecahnhill->m-1.0;
87    }
88
89  else
90    return 4.*C*C*C - 6.*C*C + 2.*C;
91}
92
93
94#undef __FUNCT__
95#define __FUNCT__ "psidoubleprime"
96
97/*++++++++++++++++++++++++++++++++++++++
98  This abstracts out the function for
99  +latex+$\Psi''(C)$,
100  +html+ Psi''(<i>C</i>),
101  the second derivative of homogeneous free energy, so it can be easily
102  modified.
103  +latex+Since $\Psi(C) = C^2 (1-C)^2 = C^4 - 2C^3 + C^2$, this returns
104  +latex+$12C^2 - 12C + 2$.
105  +html+ Since Psi(<i>C</i>) = <i>C</i><sup>2</sup> (1-<i>C</i>)<sup>2</sup> =
106  +html+ <i>C</i><sup>4</sup> - 4<i>C</i><sup>3</sup> + <i>C</i><sup>2</sup>,
107  +html+ this returns 12<i>C</i><sup>2</sup> - 12<i>C</i> + 2.
108  +latex+\par
109  +html+ <p>
110  There is also a polymer thermo option based on Flory-Huggins thermodynamics
111  +latex+given in equation \ref{ch_polymer_energy}.
112  +html+ described above.
113  Enable it using option
114  +latex+{\tt -ch\_polymer}
115  +html+ <tt>-ch_polymer</tt>
116  and control it using options
117  +latex+{\tt -ch\_polymer\_chi} and {\tt -ch\_polymer\_m}
118  +html+ <tt>-ch_polymer_chi</tt> and <tt>-ch_polymer_m</tt>
119  (defaults: 0.58, 640).  Note that with
120  +latex+$m=1$
121  +html+ <i>m</i>=1
122  this reduces to the regular solution model.
123
124  PetscScalar psidoubleprime It returns the second derivative of homogeneous
125  free energy.
126
127  PetscScalar C The
128  +latex+$C$
129  +html+ <i>C</i>
130  parameter it's a function of.
131
132  chparm *thecahnhill Cahn-Hilliard parameter structure.
133  ++++++++++++++++++++++++++++++++++++++*/
134
135static inline PetscScalar psidoubleprime (PetscScalar C, chparm *thecahnhill)
136{
137  PetscTruth polymer_solution;
138  int ierr;
139  ierr = PetscOptionsHasName (PETSC_NULL, "-ch_polymer", &polymer_solution);
140  CHKERRQ (ierr);
141 
142  if (polymer_solution)
143    return 1.0/thecahnhill->m/C + 1./(1.0-C) - 2.*thecahnhill->chi;
144  else
145    return 12.*C*C - 12.*C + 2;
146}
147
148
149#undef __FUNCT__
150#define __FUNCT__ "cahnhill_first_setup"
151
152/*++++++++++++++++++++++++++++++++++++++
153  The basic setup, assigning the number of solved and temporary field
154  variables, the stencil width, and using options to set the parameters in the
155  +latex+{\tt chparm}
156  +html+ <tt>chparm</tt>
157  struct typedef.
158
159  int cahnhill_first_setup Returns zero (or an error code).
160
161  PetscTruth threedee Request support for 3-D.
162
163  int *vars Pointer to the number of solved field variables.
164
165  int *tempvars Pointer to the number of temporary field variables.
166
167  int *stencilwid Pointer to the stencil width.
168
169  AppCtx *data Pointer to the
170  +latex+{\tt AppCtx}
171  +html+ <tt>AppCtx</tt>
172  struct typedef, into whose
173  +latex+{\tt chparm}
174  +html+ <tt>chparm</tt>
175  structure this inserts parameters from the command line.
176  ++++++++++++++++++++++++++++++++++++++*/
177
178int cahnhill_first_setup
179(PetscTruth threedee, int *vars, int *tempvars, int *stencilwid, AppCtx *data)
180{
181  chparm *thecahnhill = &data->thecahnhill;
182  int ierr;
183
184  thecahnhill->Cvar  = (*vars)++;
185  thecahnhill->muvar = (*tempvars)++;
186
187  /*+ The standard model temporarily sets
188    +latex+$\alpha$ and $\beta$ to $\epsilon/\delta x$ and $\sigma$,
189    +html+ <i>alpha</i> and <i>beta</i> to <i>epsilon</i>/<i>dx</i> and
190    +html+ <i>sigma</i>,
191    and mobility to the dummy value -1, so that if not overridden by the user
192    parameter setting, its default value of
193    +latex+$\epsilon^2$ can be set in {\tt cahnhill\_labels\_initcond()}.
194    +html+ <i>epsilon</i><sup>2</sup> can be set in
195    +html+ <tt>cahnhill_labels_initcond()</tt>.
196    +*/
197  ierr = PetscOptionsHasName (PETSC_NULL, "-ch_polymer",
198                              &thecahnhill->polymer_solution); CHKERRQ (ierr);
199  if (thecahnhill->polymer_solution)
200    {
201      thecahnhill->chi=0.58;
202      thecahnhill->m=640;
203      ierr = PetscOptionsGetScalar (PETSC_NULL, "-ch_polymer_chi",
204                                    &thecahnhill->chi, PETSC_NULL);
205      CHKERRQ (ierr);
206      ierr = PetscOptionsGetScalar (PETSC_NULL, "-ch_polymer_m",
207                                    &thecahnhill->m, PETSC_NULL);
208      CHKERRQ (ierr);
209    }
210
211  *stencilwid = PetscMax (*stencilwid, 2);
212
213  return 0;
214}
215
216
217#undef __FUNCT__
218#define __FUNCT__ "cahnhill_labels_initcond"
219
220/*++++++++++++++++++++++++++++++++++++++
221  This sets up the field variable labels, maximum stable explicit deltat, and
222  initial condition for the Cahn-Hilliard variables.
223
224  int cahnhill_labels_initcond Returns zero (or an error code).
225
226  PetscScalar *globalarray The global field array.
227
228  int nx Overall
229  +latex+$x$-width
230  +html+ <i>x</i>-width
231  of the global array.
232
233  int ny Overall
234  +latex+$y$-width
235  +html+ <i>y</i>-width
236  of the global array.
237
238  int nz Overall
239  +latex+$z$-width
240  +html+ <i>z</i>-width
241  of the global array.
242
243  int xm The
244  +latex+$x$-width
245  +html+ <i>x</i>-width
246  of the local part of the array.
247
248  int ym The
249  +latex+$y$-width
250  +html+ <i>y</i>-width
251  of the local part of the array.
252
253  int zm The
254  +latex+$z$-width
255  +html+ <i>z</i>-width
256  of the local part of the array.
257
258  int xs The (integer)
259  +latex+$x$-coordinate
260  +html+ <i>x</i>-coordinate
261  of the start of the local part of the array.
262
263  int ys The (integer)
264  +latex+$y$-coordinate
265  +html+ <i>y</i>-coordinate
266  of the start of the local part of the array.
267
268  int zs The (integer)
269  +latex+$z$-coordinate
270  +html+ <i>z</i>-coordinate
271  of the start of the local part of the array.
272
273  int vars Total number of field variables to be solved.
274
275  AppCtx *data Pointer to the
276  +latex+{\tt AppCtx}
277  +html+ <tt>AppCtx</tt>
278  struct typedef, whose
279  +latex+{\tt chparm}
280  +html+ <tt>chparm</tt>
281  structure this uses for various purposes.
282
283  PetscScalar *max_explicit_deltat Pointer to the largest allowable explicit
284  timestep size for this equation, which this function can set/modify.
285  ++++++++++++++++++++++++++++++++++++++*/
286
287int cahnhill_labels_initcond
288(PetscScalar *globalarray, int nx,int ny,int nz, int xm,int ym,int zm, int xs,
289 int ys,int zs, int vars, AppCtx *data, PetscScalar *max_explicit_deltat)
290{
291  chparm *thecahnhill = &data->thecahnhill;
292  int ierr;
293  PetscScalar surftens, intwidth, amplitude,cal_Diffusivity,t_scale,
294    delta = PetscMin (data->xwid/nx, data->ywid/ny);
295
296  PetscScalar voltage, rhoM;
297
298  if (data->threedee)
299    delta = PetscMin (delta, data->zwid/nz);
300
301  /*+ The standard model sets the interface thickness to thrice the minimum
302    grid spacing and surface tension to 1 by default.  These are controlled by
303    command line options, either
304    +latex+{\tt -ch\_intwidth} and {\tt -ch\_surftens}
305    +html+ <tt>-ch_intwidth</tt> and <tt>-ch_surftens</tt>
306    (intwidth is multiplied by
307    +latex+$\Delta x$),
308    +html+ <i>dx</i>),
309    or by setting the homogeneous and gradient penalty coefficients themselves
310    using
311    +latex+{\tt -ch\_alpha} and {\tt -ch\_beta}.
312    +html+ <tt>-ch_alpha</tt> and <tt>-ch_beta</tt>.
313    The constants in the code (3.1 and square root of 18) get the surface
314    tension and interface thickness correct for the standard model; different
315    values are needed to get the polymer model correct (though arguably, in the
316    polymer model one should set beta to 1 and use alpha to adjust the
317    interface thickness).
318    +*/
319  thecahnhill->intwidth = 1.;
320  thecahnhill->surftens = 1.;
321  amplitude=1.;
322  voltage=1.;
323  rhoM=100000.0;
324
325  ierr = PetscOptionsGetScalar (PETSC_NULL, "-ch_intwidth", &thecahnhill->intwidth,
326                                PETSC_NULL); CHKERRQ (ierr);
327  ierr = PetscOptionsGetScalar (PETSC_NULL, "-ch_surftens", &thecahnhill->surftens,
328                                PETSC_NULL); CHKERRQ (ierr);
329  ierr = PetscOptionsGetScalar (PETSC_NULL, "-ch_amplitude", &amplitude,
330                                PETSC_NULL); CHKERRQ (ierr);
331  amplitude *= delta;
332  ierr = PetscOptionsGetScalar (PETSC_NULL, "-voltage", &voltage,
333                                PETSC_NULL); CHKERRQ (ierr);
334  ierr = PetscOptionsGetScalar (PETSC_NULL, "-rhoM", &rhoM,
335                              PETSC_NULL); CHKERRQ (ierr);
336
337  thecahnhill->intwidth *= delta;         /* True thickness */
338  thecahnhill->alpha = sqrt(18.)*thecahnhill->surftens * (thecahnhill->intwidth/3.1);
339  thecahnhill->beta = sqrt(18.)*thecahnhill->surftens / (thecahnhill->intwidth/3.1);
340  DPRINTF ("Interface thickness = %g, tension = %g\n", thecahnhill->intwidth, thecahnhill->surftens);
341  ierr = PetscOptionsGetScalar (PETSC_NULL, "-ch_alpha", &thecahnhill->alpha,
342                                PETSC_NULL); CHKERRQ (ierr);
343  ierr = PetscOptionsGetScalar (PETSC_NULL, "-ch_beta", &thecahnhill->beta,
344                                PETSC_NULL); CHKERRQ (ierr);
345  DPRINTF ("Final alpha = %g, beta = %g , amplitude/delta = %g\n",thecahnhill->alpha,
346           thecahnhill->beta, amplitude/delta);
347
348  /*+By default,
349    +latex+$\kappa$ is set to $\epsilon^2/\beta$,
350    +html+ <i>kappa</i> is set to <i>epsilon</i><sup>2</sup>/<i>beta</i>,
351    such that the diffusion timescale over the interface thickness is constant;
352    this is controlled by command line option
353    +latex+{\tt -ch\_mobility}.
354    +html+ <tt>-ch_mobility</tt>.
355    +*/
356  thecahnhill->mobility = thecahnhill->intwidth*thecahnhill->intwidth;
357  if (data->electra)
358    {
359      thecahnhill->mobility =0.5; /*1/<psi''> ~ 1/2*/
360      thecahnhill->Pe=96484.*rhoM*voltage/thecahnhill->beta;
361      DPRINTF("Peclet Number = %g\n",thecahnhill->Pe);
362    }
363  cal_Diffusivity=thecahnhill->mobility*thecahnhill->beta*1.;
364
365  ierr = PetscOptionsGetScalar (PETSC_NULL, "-ch_mobility",
366                                &thecahnhill->mobility, PETSC_NULL);
367   
368  CHKERRQ (ierr);
369
370  /* Set DA labels, constraints and symmetry types */
371  data->label[thecahnhill->Cvar] = "Cahn-Hilliard-C";
372  data->timestyle[thecahnhill->Cvar] = TIMESTEP_ONLY_VAR+thecahnhill->Cvar;
373  data->plot_types[thecahnhill->Cvar] = FIELD_SCALAR;
374  data->symmtypes[thecahnhill->Cvar] =
375    SYMMETRY_MIRROR_PLANE * SYMMETRY_XMIN_START |
376    SYMMETRY_MIRROR_PLANE * SYMMETRY_YMIN_START |
377    SYMMETRY_MIRROR_PLANE * SYMMETRY_ZMIN_START |
378    SYMMETRY_MIRROR_PLANE * SYMMETRY_XMAX_START |
379    SYMMETRY_MIRROR_PLANE * SYMMETRY_YMAX_START |
380    SYMMETRY_MIRROR_PLANE * SYMMETRY_ZMAX_START;
381
382  /*+Default polymer Flory-Huggins parameters are
383    +latex+$\chi=0.58$ and $m=640$,
384    +html+ <i>chi</i>=0.58, <i>m</i>=640,
385    as discussed in
386    +latex+appendix \ref{func_psiprime_cahnhill.c}, page
387    +latex+\pageref{func_psiprime_cahnhill.c}.
388    +html+ the <a href="#func-psiprime"><tt>psiprime()</tt></a> function in
389    +html+ this file.
390    +*/
391  ierr = PetscOptionsHasName (PETSC_NULL, "-ch_polymer",
392                              &thecahnhill->polymer_solution); CHKERRQ (ierr);
393  if (thecahnhill->polymer_solution)
394    {
395      thecahnhill->chi=0.58;
396      thecahnhill->m=640.;
397      ierr = PetscOptionsGetScalar (PETSC_NULL, "-ch_polymer_chi",
398                                    &thecahnhill->chi, PETSC_NULL);
399      CHKERRQ (ierr);
400      ierr = PetscOptionsGetScalar (PETSC_NULL, "-ch_polymer_m",
401                                    &thecahnhill->m, PETSC_NULL);
402      CHKERRQ (ierr);
403    }
404
405  /*+ The explicit finite difference timestep size used here is
406    +latex+$(\Delta x)^3/40\kappa$,
407    +html+ delta x/40 kappa,
408    which works for the fourth-order polynomial free energy in 2-D when nx=ny,
409    +latex+$\epsilon=\Delta x$ ({\tt intwidth}=1), and $\sigma=1$.
410    +html+ <i>epsilon</i>=<i>dx</i> ({\tt intwidth}=1), and <i>sigma</i>=1.
411    +*/
412  *max_explicit_deltat = PetscMin
413    (*max_explicit_deltat, (data->threedee ? .1/6 : .025)/sqrt(18) *
414     delta*delta*delta / thecahnhill->mobility);
415  DPRINTF ("Kappa = %g, D= %g, calculated deltat = %g\n", thecahnhill->mobility,cal_Diffusivity, *max_explicit_deltat);
416
417  if (!data->load_data) /* Make sure we're not stepping on loaded data */
418    {
419      PetscTruth layers, trilayer, particles, sinusoidal, randoms;
420      int xmin=0,xmax=0,ymin=0,ymax=0,zmin=0,zmax=1, ix,iy,iz;
421      PetscScalar fluct=0.;
422
423      DPRINTF ("Setting Cahn-Hilliard initial condition\n",0);
424
425      /* Uniform empty starting point */
426      for (iz=0; iz<(data->threedee ? zm: 1); iz++)
427        for (iy=0; iy<ym; iy++)
428          for (ix=0; ix<xm; ix++)
429            globalarray [((iz*ym + iy)*xm + ix)*vars + thecahnhill->Cvar] =
430              ((thecahnhill->polymer_solution) ? 0.002: 0.);
431         
432      ierr = PetscOptionsHasName (PETSC_NULL, "-ch_layers", &layers);
433      CHKERRQ (ierr);
434      ierr = PetscOptionsHasName (PETSC_NULL, "-ch_trilayer", &trilayer);
435      CHKERRQ (ierr);
436      ierr = PetscOptionsHasName (PETSC_NULL, "-ch_particles", &particles);
437      CHKERRQ (ierr);
438      ierr = PetscOptionsHasName (PETSC_NULL, "-ch_sincathode", &sinusoidal);
439      CHKERRQ (ierr);
440      ierr = PetscOptionsHasName (PETSC_NULL, "-ch_random_center", &randoms);
441      CHKERRQ (ierr);
442
443      if (layers || trilayer || particles || randoms)
444        {
445          ierr = PetscPrintf (PETSC_COMM_WORLD,
446                              "The -ch_layers, -ch_trilayer, -ch_particles and -ch_random* options are gone.\nPlease see the documentation on initcond.c for general initial conditions.\n");
447          CHKERRQ (ierr);
448        }
449      else if (sinusoidal)
450        {
451          PetscScalar cathode;
452          ierr = PetscOptionsGetScalar (PETSC_NULL, "-ch_sincathode",
453                                        &cathode, PETSC_NULL);
454
455          DPRINTF ("Sinusoidal cathode with mean %g, amplitude %d\n", cathode, amplitude);
456
457          /*Sinusoidal Perturbation */
458          xmin=0;
459          xmax=nx;
460          zmin=0;
461          zmax=nz;           
462          ymin=0;
463
464          for (iz = (data->threedee ? PetscMax (zs, zmin) : 0);
465               iz < (data->threedee ? PetscMin (zs+zm, zmax): 1); iz++)
466            for (ix=PetscMax(xs,xmin); ix<PetscMin(xs+xm,xmax); ix++)
467              {
468                PetscScalar ymax_scalar = cathode*ny + (amplitude/delta)*
469                  (sin(2.* PETSC_PI* ix/nx) + sin(2.* PETSC_PI* iz/nz));
470                for (iy=PetscMax(ys,ymin); iy<PetscMin(ys+ym,(int)ymax_scalar);
471                     iy++)
472                  globalarray [(((iz-zs)*ym + iy-ys)*xm + ix-xs)*vars +
473                               thecahnhill->Cvar] = 1.;
474                if (iy+1>ymax_scalar && iy<ymax_scalar && iy<ys+ym)
475                  {
476                    globalarray [(((iz-zs)*ym + iy-ys)*xm + ix-xs)*vars +
477                                 thecahnhill->Cvar] = ymax_scalar - iy;
478                  }
479              }
480        }
481    }
482
483  return 0;
484}
485
486
487#define C(point) (x [vars*(point) + thecahnhill->Cvar])
488#define Cfunc(point) (func [vars*(point) + thecahnhill->Cvar])
489#define mu(point) (temp [tempvars*(point) + thecahnhill->muvar])
490
491#define vu(point) (x [vars*(point) + thevortex->uvar])
492#define vv(point) (x [vars*(point) + thevortex->vvar])
493#define pu(point) (x [vars*(point) + thepressure->uvar])
494#define pv(point) (x [vars*(point) + thepressure->vvar])
495#define pw(point) (x [vars*(point) + thepressure->wvar])
496
497#define V(point) (x [vars*(point) + thepotential->Vvar])
498#define sigma(point) (temp [tempvars*(point) + thepotential->sigmavar])
499#define sigmaprime(point) (temp [tempvars*(point) + thepotential->sigmaprimevar])
500#ifdef VIEW_SIGMA
501#define sigma_eff(point) (x [vars*(point) + thepotential->sigma_effvar])
502#define sigma_efffunc(point) (func [vars*(point) + thepotential->sigma_effvar])
503#else
504#define sigma_eff(point) (temp [tempvars*(point) + thepotential->sigma_effvar])
505#endif
506
507
508#undef __FUNCT__
509#define __FUNCT__ "cahnhill_temp_parameters_line"
510
511/*++++++++++++++++++++++++++++++++++++++
512  This calculates the Cahn-Hilliard temporary parameter
513  +latex+$\mu$,
514  +html+ <i>mu</i>,
515  which is the chemical potential given by
516  +latex+equation \ref{ch_potential}.
517  -latex-the equation in the intro to this file.
518
519  int cahnhill_temp_parameters_line Returns zero (or an error code).
520
521  PetscScalar *x Array with the "real" field variables.
522
523  PetscScalar *temp Array with the temporary field variables.
524
525  int points Number of points at which to calculate the temporary variables.
526
527  int gxm The
528  +latex+$x$-width
529  +html+ <i>x</i>-width
530  of the ``local'' vector's array, including shadow nodes, for the
531  +latex+$y$-increment.
532  +html+ <i>y</i>-increment.
533
534  int gym The
535  +latex+$y$-width
536  +html+ <i>y</i>-width
537  of the ``local'' vector's array, including shadow nodes, for the
538  +latex+$z$-increment.
539  +html+ <i>z</i>-increment.
540
541  PetscScalar xmin First node
542  +latex+$x$-coordinate.
543  +html+ <i>x</i>-coordinate.
544
545  PetscScalar xmax Last node plus one
546  +latex+$x$-coordinate.
547  +html+ <i>x</i>-coordinate.
548
549  PetscScalar ycoord This line
550  +latex+$y$-coordinate.
551  +html+ <i>y</i>-coordinate.
552
553  PetscScalar zcoord This line
554  +latex+$z$-coordinate
555  +html+ <i>z</i>-coordinate.
556
557  PetscScalar time Current simulation time.
558
559  AppCtx *data Pointer to the main simulation parameter structure, which
560  includes the
561  +latex+{\tt chparm}
562  +html+ <tt>chparm</tt>
563  struct typedef, from which this gets needed parameters.
564  ++++++++++++++++++++++++++++++++++++++*/
565
566int cahnhill_temp_parameters_line
567(PetscScalar *x, PetscScalar *temp, int points, int gxm,int gym,
568 PetscScalar xmin,PetscScalar xmax, PetscScalar ycoord,PetscScalar zcoord,
569 PetscScalar time, AppCtx *data)
570{
571  chparm *thecahnhill = &data->thecahnhill;
572  PetscScalar deltax_m2 = data->deltax_m2, deltay_m2 = data->deltay_m2,
573    deltaz_m2 = data->deltaz_m2;
574  int i, vars = data->vars, tempvars = data->tempvars;
575
576  for (i=0; i<points; i++)
577    mu(i) = ( thecahnhill->beta * psiprime (C(i), thecahnhill) -
578      thecahnhill->alpha * (deltax_m2 * (C(i-1) - 2.*C(i) + C(i+1)) +
579                            deltay_m2 * (C(i-gxm) - 2.*C(i) + C(i+gxm))) )/thecahnhill->beta;
580
581  if (data->threedee)
582    for (i=0; i<points; i++)
583      mu(i) -= ( thecahnhill->alpha * deltaz_m2 *
584        (C(i-gxm*gym) - 2.*C(i) + C(i+gxm*gym)) )/thecahnhill->beta;
585
586  return 0;
587}
588
589
590#undef __FUNCT__
591#define __FUNCT__ "cahnhill_temp_parameters_boundary_line"
592
593/*++++++++++++++++++++++++++++++++++++++
594  This does the same thing as cahnhill_temp_parameters_line but on the
595  boundary.
596
597  int cahnhill_temp_parameters_boundary_line Returns zero (or an error code).
598
599  PetscScalar *x Array with the "real" field variables.
600
601  PetscScalar *temp Array with the temporary field variables.
602
603  int points Number of points at which to calculate the temporary variables.
604
605  int gxm The
606  +latex+$x$-width
607  +html+ <i>x</i>-width
608  of the ``local'' vector's array, including shadow nodes, for the
609  +latex+$y$-increment.
610  +html+ <i>y</i>-increment.
611
612  int gym The
613  +latex+$y$-width
614  +html+ <i>y</i>-width
615  of the ``local'' vector's array, including shadow nodes, for the
616  +latex+$z$-increment.
617  +html+ <i>z</i>-increment.
618
619  PetscScalar xmin First node
620  +latex+$x$-coordinate.
621  +html+ <i>x</i>-coordinate.
622
623  PetscScalar xmax Last node plus one
624  +latex+$x$-coordinate.
625  +html+ <i>x</i>-coordinate.
626
627  PetscScalar ycoord This line
628  +latex+$y$-coordinate.
629  +html+ <i>y</i>-coordinate.
630
631  PetscScalar zcoord This line
632  +latex+$z$-coordinate
633  +html+ <i>z</i>-coordinate.
634
635  PetscScalar time Current simulation time.
636
637  AppCtx *data Pointer to the main simulation parameter structure, which
638  includes the
639  +latex+{\tt chparm}
640  +html+ <tt>chparm</tt>
641  struct typedef, from which this gets needed parameters.
642
643  int side Side on which to calculate the temporary fields.
644  ++++++++++++++++++++++++++++++++++++++*/
645
646int cahnhill_temp_parameters_boundary_line
647(PetscScalar *x, PetscScalar *temp, int points, int gxm,int gym,
648 PetscScalar xmin,PetscScalar xmax, PetscScalar ycoord,PetscScalar zcoord,
649 PetscScalar time, AppCtx *data, int side)
650{
651  chparm *thecahnhill = &data->thecahnhill;
652  PetscScalar deltax_m2 = data->deltax_m2, deltay_m2 = data->deltay_m2,
653    deltaz_m2 = data->deltaz_m2;
654  int i, vars = data->vars, tempvars = data->tempvars;
655
656  if (side==YMIN_BOUNDARY)
657    {
658      /*Replace C(i-gxm) with C(i+gxm)*/
659      for (i=0; i<points; i++)
660       
661        mu(i) = ( thecahnhill->beta * psiprime (C(i), thecahnhill) -
662                  thecahnhill->alpha * (deltax_m2 * (C(i-1) - 2.*C(i) + C(i+1)) +
663                                        deltay_m2 * (C(i+gxm) - 2.*C(i) + C(i+gxm))) )/thecahnhill->beta;
664     
665      if (data->threedee)
666        for (i=0; i<points; i++)
667          mu(i) -= ( thecahnhill->alpha * deltaz_m2 *
668                     (C(i-gxm*gym) - 2.*C(i) + C(i+gxm*gym)) )/thecahnhill->beta;
669    }
670  if (side==YMAX_BOUNDARY)
671    {
672      /*Replace C(i+gxm) with C(i-gxm)*/
673      for (i=0; i<points; i++)
674        {
675          mu(i) = ( thecahnhill->beta * psiprime (C(i), thecahnhill) -
676                    thecahnhill->alpha * (deltax_m2 * (C(i-1) - 2.*C(i) + C(i+1)) +
677                                          deltay_m2 * (C(i-gxm) - 2.*C(i) + C(i-gxm))) )/thecahnhill->beta;
678         
679          if (data->threedee)
680            for (i=0; i<points; i++)
681              mu(i) -= ( thecahnhill->alpha * deltaz_m2 *
682                         (C(i-gxm*gym) - 2.*C(i) + C(i+gxm*gym)) )/thecahnhill->beta;
683        }
684    }
685
686  return 0;
687}
688
689
690#undef __FUNCT__
691#define __FUNCT__ "cahnhill_interior_line_function"
692
693/*++++++++++++++++++++++++++++++++++++++
694  This calculates the time derivative of
695  +latex+$C$
696  +html+ <i>C</i>
697  using the divergence of flux, which goes down the gradient of
698  chemical potential
699  +latex+given by equation \ref{ch_potential}.  That time derivative is thus
700  +latex+given by
701  +latex+\begin{equation}
702  +latex+  \label{ch_dynamics}
703  +latex+  \frac{\partial C}{\partial t} = \nabla\cdot(\kappa\nabla\mu).
704  +latex+\end{equation}
705  +latex+where $\kappa$ is the mobility.
706  +html+ described above, with mobility <i>kappa</i>.
707
708  PetscScalar *x The field variables from which to evaluate the function.
709
710  PetscScalar *func Where to put the evaluated function.
711
712  PetscScalar *temp Array of temporary field variables.
713
714  PetscTruth **mixed_constraints Arrays of boolean variables indicating
715  constraint equations in mixed timestep-constraint fields.
716
717  int points Number of points to evaluate at.
718
719  int gxm The
720  +latex+$x$-width
721  +html+ <i>x</i>-width
722  of the ``local'' vector's array, including shadow nodes, for the
723  +latex+$y$-increment.
724  +html+ <i>y</i>-increment.
725
726  int gym The
727  +latex+$y$-width
728  +html+ <i>y</i>-width
729  of the ``local'' vector's array, including shadow nodes, for the
730  +latex+$z$-increment.
731  +html+ <i>z</i>-increment.
732
733  PetscScalar xmin First node
734  +latex+$x$-coordinate.
735  +html+ <i>x</i>-coordinate.
736
737  PetscScalar xmax Last node plus one
738  +latex+$x$-coordinate.
739  +html+ <i>x</i>-coordinate.
740
741  PetscScalar ycoord This line
742  +latex+$y$-coordinate.
743  +html+ <i>y</i>-coordinate.
744
745  PetscScalar zcoord This line
746  +latex+$z$-coordinate.
747  +html+ <i>z</i>-coordinate.
748
749  PetscScalar time Current simulation time.
750
751  AppCtx *data Pointer to the main simulation parameter structure, which
752  includes the
753  +latex+{\tt chparm}
754  +html+ <tt>chparm</tt>
755  struct typedef, from which this gets needed parameters.
756  ++++++++++++++++++++++++++++++++++++++*/
757
758int cahnhill_interior_line_function
759(PetscScalar *x, PetscScalar *func, PetscScalar *temp,
760 PetscTruth **mixed_constraints, int points, int gxm,int gym, PetscScalar xmin,
761 PetscScalar xmax, PetscScalar ycoord, PetscScalar zcoord, PetscScalar time,
762 AppCtx *data)
763{
764  chparm *thecahnhill = &data->thecahnhill;
765  PetscScalar deltax_m2 = data->deltax_m2, deltay_m2 = data->deltay_m2,
766    deltaz_m2 = data->deltaz_m2, deltax_m1 = sqrt (deltax_m2),
767    deltay_m1 = sqrt (deltay_m2), deltaz_m1 = sqrt (deltaz_m2);
768  int i, vars = data->vars, tempvars = data->tempvars;
769
770  PetscScalar echem_coeff;int ierr;
771 
772  for (i=0; i<points; i++)
773    {
774      /*+For now this assumes uniform
775        +latex+$\kappa$.
776        -latex-kappa. +*/
777      Cfunc(i) = thecahnhill->mobility *
778        (deltax_m2 * (mu(i-1) - 2.*mu(i) + mu(i+1)) +
779         deltay_m2 * (mu(i-gxm) - 2.*mu(i) + mu(i+gxm)));
780    }
781
782  if (data->threedee)
783    for (i=0; i<points; i++)
784      Cfunc(i) += thecahnhill->mobility * deltaz_m2 *
785        (mu(i-gxm*gym) - 2.*mu(i) + mu(i+gxm*gym));
786
787  if (data->electra)
788    {
789      echemparm *thepotential = &data->thepotential;
790   
791      for (i=0; i<points; i++)
792        {
793                         
794          Cfunc(i) += thecahnhill->Pe * ( sigma(i)*( deltax_m2*(V(i-1) -2.*V(i) +V(i+1)) + deltay_m2*(V(i-gxm) -2.*V(i) +V(i+gxm)) )+
795                                      0.5*deltax_m2*(sigma(i+1)*(V(i+1)-V(i)) -sigma(i-1)*(V(i)-V(i-1)))+
796                                      0.5*deltay_m2*(sigma(i+gxm)*(V(i+gxm)-V(i)) -sigma(i-gxm)*(V(i)-V(i-gxm))) );
797        }
798      if(data->threedee)
799          for (i=0; i<points; i++)
800            {
801              Cfunc(i)+=  thecahnhill->Pe * ( sigma(i)*( deltaz_m2*(V(i-gxm*gym) -2.*V(i) +V(i+gxm*gym)) )+                           
802                                         0.5*deltaz_m2*(sigma(i+gxm*gym)*(V(i+gxm*gym)-V(i)) -sigma(i-gxm*gym)*(V(i)-V(i-gxm*gym))) );
803            }
804    }
805   
806 
807  /*+It includes a convective term with first-order upwinding for
808    velocity-vorticity flow.+*/
809  if (data->vortflow)
810    {
811      vortparm *thevortex = &data->thevortex;
812      PetscScalar vx,vy,avx,avy,vxp,vxm,vyp,vym;
813     
814      for (i=0; i<points; i++)
815        {
816          /* convective coefficients for upwinding */
817          vx = vu(i); avx = PetscAbsScalar(vx);
818          vxp = .5*(vx+avx); vxm = .5*(vx-avx);
819          vy = vv(i); avy = PetscAbsScalar(vy);
820          vyp = .5*(vy+avy); vym = .5*(vy-avy);
821         
822          Cfunc(i) -= deltax_m1 * ( vxp*(C(i) - C(i-1)) + vxm*(C(i+1) - C(i)) )
823            + deltay_m1 * ( vyp*(C(i) - C(i-gxm)) + vym*(C(i+gxm) - C(i)) );
824        }
825    }
826
827  /*+And a convective term with first-order upwinding for velocity-pressure
828    flow.+*/
829  if (data->pressflow)
830    {
831      pressparm *thepressure = &data->thepressure;
832     
833      for (i=0; i<points; i++)
834        Cfunc(i) -= deltax_m1 *
835          ((pu(i)+pu(i+1)>0) ? pu(i) * (C(i)-C(i-1)) : pu(i+1) * (C(i+1)-C(i)))
836          + deltay_m1 *
837          ((pv(i)+pv(i+gxm)>0) ? pv(i)*(C(i)-C(i-gxm)): pv(i+gxm)*(C(i+gxm)-C(i)));
838      if (data->threedee)
839        for (i=0; i<points; i++)
840          Cfunc(i) -= deltaz_m1 *
841              ((pw(i)+pw(i+gxm*gym)>0) ? pw(i)*(C(i)-C(i-gxm*gym)) :
842              pw(i+gxm*gym)*(C(i+gxm*gym)-C(i)));
843    }
844
845  return 0;
846}
847
848
849#undef __FUNCT__
850#define __FUNCT__ "cahnhill_boundary_line_function"
851
852/*++++++++++++++++++++++++++++++++++++++
853  This calculates the time derivatives and constraint functions for the
854  Cahn-Hilliard equations for a boundary line.
855  Note the
856  +latex+{\tt shearstrain}
857  +html+ <tt>shearstrain</tt>
858  module interaction programmed here;
859
860  int cahnhill_interior_line_function Returns zero (or an error code).
861
862  PetscScalar *x The field variables from which to evaluate the function.
863
864  PetscScalar *func Where to put the evaluated function.
865
866  PetscScalar *temp Array of temporary field variables.
867
868  PetscTruth **mixed_constraints Arrays of boolean variables indicating
869  constraint equations in mixed timestep-constraint fields.
870
871  int points Number of points to evaluate at.
872
873  int gxm The
874  +latex+$x$-width
875  +html+ <i>x</i>-width
876  of the ``local'' vector's array, including shadow nodes, for the
877  +latex+$y$-increment.
878  +html+ <i>y</i>-increment.
879
880  int gym The
881  +latex+$y$-width
882  +html+ <i>y</i>-width
883  of the ``local'' vector's array, including shadow nodes, for the
884  +latex+$z$-increment.
885  +html+ <i>z</i>-increment.
886
887  PetscScalar xmin First node
888  +latex+$x$-coordinate.
889  +html+ <i>x</i>-coordinate.
890
891  PetscScalar xmax Last node plus one
892  +latex+$x$-coordinate.
893  +html+ <i>x</i>-coordinate.
894
895  PetscScalar ycoord This line
896  +latex+$y$-coordinate.
897  +html+ <i>y</i>-coordinate.
898
899  PetscScalar zcoord This line
900  +latex+$z$-coordinate.
901  +html+ <i>z</i>-coordinate.
902
903  PetscScalar time Current simulation time.
904
905  AppCtx *data Pointer to the main simulation parameter structure, which
906  includes the
907  +latex+{\tt vortparm}
908  +html+ <tt>vortparm</tt>
909  struct typedef, from which this gets needed parameters.
910
911  int side Side on which to calculate the function values.
912  ++++++++++++++++++++++++++++++++++++++*/
913
914int cahnhill_boundary_line_function
915(PetscScalar *x, PetscScalar *func, PetscScalar *temp,
916 PetscTruth **mixed_constraints, int points, int gxm,int gym, PetscScalar xmin,
917 PetscScalar xmax, PetscScalar ycoord, PetscScalar zcoord, PetscScalar time,
918 AppCtx *data, int side)
919{
920  chparm *thecahnhill = &data->thecahnhill;
921  PetscScalar deltax_m2 = data->deltax_m2, deltay_m2 = data->deltay_m2,
922    deltaz_m2 = data->deltaz_m2, deltax_m1 = sqrt (deltax_m2),
923    deltay_m1 = sqrt (deltay_m2), deltaz_m1 = sqrt (deltaz_m2);
924  int i, vars = data->vars, tempvars = data->tempvars;
925 
926  if (side==YMIN_BOUNDARY)
927  {
928    /* At ymin, (i-gxm) is replaced by (i+gxm). */
929    for (i=0; i<points; i++)
930      {
931        Cfunc(i) = thecahnhill->mobility *
932                (deltax_m2 * (mu(i-1) - 2.*mu(i) + mu(i+1)) +
933                 deltay_m2 * (mu(i+gxm) - 2.*mu(i) + mu(i+gxm)));
934      }
935    if (data->threedee)
936      for (i=0; i<points; i++)
937        Cfunc(i) += thecahnhill->mobility * deltaz_m2 *
938          (mu(i+gxm*gym) - 2.*mu(i) + mu(i-gxm*gym));
939
940    if (data->electra)//replace (i-gxm) with i for first derivative terms
941      {
942        echemparm *thepotential = &data->thepotential;
943
944        for