https://github.com/geodynamics/citcoms
Revision 45be8f2e32748cd56c3154bbdcd61da3fddda4bd authored by Eh Tan on 09 March 2007, 00:25:03 UTC, committed by Eh Tan on 09 March 2007, 00:25:03 UTC
* Seperating composition codes from tracer codes, several struct members in E->trace are moved to E->composition
* Add chemical buoyancy term
* Renamed thermal_buoyancy() to get_buoyancy() to reflect the fact that this function computes buoyancy according to temperature/composition/phase
* Fix and optimize the fix_*() functions
* Remove some static variables, or converte them to const
* Change the type of E->SinCos from float to double, and replace E->trace.DSinCos
* Provide default values for "required" input parameters
* Renamed tracer_restart to tracer_ic_method, also remapped the options
* Removed option for Cartesian tracer input and trace.iwrite_tracers_every
* Replaced trace.itracer_type by composition.ichemical_buoyancy
* Optionally output tracers and composition fields

1 parent 068a4d5
Raw File
Tip revision: 45be8f2e32748cd56c3154bbdcd61da3fddda4bd authored by Eh Tan on 09 March 2007, 00:25:03 UTC
A big patch for tracers and composition:
Tip revision: 45be8f2
Composition_related.c
/*
 *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 *
 *<LicenseText>
 *
 * CitcomS by Louis Moresi, Shijie Zhong, Lijie Han, Eh Tan,
 * Clint Conrad, Michael Gurnis, and Eun-seo Choi.
 * Copyright (C) 1994-2005, California Institute of Technology.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 *</LicenseText>
 *
 *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 */

#include <math.h>
#include "global_defs.h"
#include "parsing.h"
#include "parallel_related.h"
#include "composition_related.h"


static void initialize_old_composition(struct All_variables *E);


void composition_input(struct All_variables *E)
{
    int m = E->parallel.me;

    input_int("chemical_buoyancy",&(E->composition.ichemical_buoyancy),
              "1,0,nomax",m);

    if (E->composition.ichemical_buoyancy==1) {

	input_double("buoyancy_ratio",
		     &(E->composition.buoyancy_ratio),"1.0",m);

	/* ibuoy_type=0 (absolute method) */
	/* ibuoy_type=1 (ratio method) */

	input_int("buoy_type",&(E->composition.ibuoy_type),"1,0,nomax",m);
	if (E->composition.ibuoy_type!=1) {
	    fprintf(stderr,"Terror-Sorry, only ratio method allowed now\n");
	    fflush(stderr);
	    parallel_process_termination();
	}

	if (E->trace.ic_method==2) {
	    input_int("reset_initial_composition",
		      &(E->composition.ireset_initial_composition),"0",m);
	}

        input_double("z_interface",&(E->composition.z_interface),"0.5",m);

    }


    /* compositional rheology */

    /* icompositional_rheology=0 (off) */
    /* icompositional_rheology=1 (on) */

    input_int("compositional_rheology",
	      &(E->composition.icompositional_rheology),"1,0,nomax",m);

    if (E->composition.icompositional_rheology==1) {
	input_double("compositional_prefactor",
		     &(E->composition.compositional_rheology_prefactor),
		     "1.0",m);
    }

}



void composition_setup(struct All_variables *E)
{

    E->composition.on = 0;
    if (E->composition.ichemical_buoyancy==1 ||
        E->composition.icompositional_rheology)
        E->composition.on = 1;

    if (E->composition.ichemical_buoyancy==1 && E->composition.ibuoy_type==1) {
	initialize_old_composition(E);
	fill_composition(E);
    }

}



void init_tracer_composition(struct All_variables *E)
{
    int j, kk, number_of_tracers;
    double rad;

    for (j=1;j<=E->sphere.caps_per_proc;j++) {

        number_of_tracers = E->trace.itrac[j][0];
        for (kk=1;kk<=number_of_tracers;kk++) {
            rad = E->trace.rtrac[j][2][kk];

            if (rad<=E->composition.z_interface) E->trace.etrac[j][0][kk]=1.0;
            if (rad>E->composition.z_interface) E->trace.etrac[j][0][kk]=0.0;
        }
    }
    return;
}


void write_composition_instructions(struct All_variables *E)
{

    if (E->composition.ichemical_buoyancy==0)
	    fprintf(E->trace.fpt,"Passive Tracers\n");

    if (E->composition.ichemical_buoyancy==1)
        fprintf(E->trace.fpt,"Active Tracers\n");


    if (E->composition.ibuoy_type==1) fprintf(E->trace.fpt,"Ratio Method\n");
    if (E->composition.ibuoy_type==0) fprintf(E->trace.fpt,"Absolute Method\n");

    fprintf(E->trace.fpt,"Buoyancy Ratio: %f\n", E->composition.buoyancy_ratio);


    if (E->composition.ireset_initial_composition==0)
	fprintf(E->trace.fpt,"Using old initial composition from tracer files\n");
    else
	fprintf(E->trace.fpt,"Resetting initial composition\n");



    if (E->composition.icompositional_rheology==0) {
	fprintf(E->trace.fpt,"Compositional Rheology - OFF\n");
    }
    else if (E->composition.icompositional_rheology>0) {
	fprintf(E->trace.fpt,"Compositional Rheology - ON\n");
	fprintf(E->trace.fpt,"Compositional Prefactor: %f\n",
		E->composition.compositional_rheology_prefactor);
    }


    fflush(E->trace.fpt);
    fflush(stderr);

}


/************ FILL COMPOSITION ************************/
void fill_composition(struct All_variables *E)
{

    void compute_elemental_composition_ratio_method();
    void map_composition_to_nodes();

    /* Currently, only the ratio method works here.                */
    /* Will have to come back here to include the absolute method. */

    /* ratio method */

    if (E->composition.ibuoy_type==1)
	{
	    compute_elemental_composition_ratio_method(E);
	}

    /* absolute method */

    if (E->composition.ibuoy_type!=1)
	{
	    fprintf(E->trace.fpt,"Error(compute...)-only ratio method now\n");
	    fflush(E->trace.fpt);
	    exit(10);
	}

    /* Map elemental composition to nodal points */

    map_composition_to_nodes(E);

    return;
}



/************ INITIALIZE OLD COMPOSITION ************************/
static void initialize_old_composition(struct All_variables *E)
{

    char output_file[200];
    char input_s[1000];

    int ibottom_node;
    int kk;
    int j;

    double zbottom;
    double time;

    FILE *fp;

    for (j=1;j<=E->sphere.caps_per_proc;j++)
	{

	    if ((E->trace.oldel[j]=(double *)malloc((E->lmesh.nel+1)*sizeof(double)))==NULL)
		{
		    fprintf(E->trace.fpt,"ERROR(fill old composition)-no memory 324c\n");
		    fflush(E->trace.fpt);
		    exit(10);
		}
	}


    if ((E->trace.ic_method==0)||(E->trace.ic_method==1))
	{
	    for (j=1;j<=E->sphere.caps_per_proc;j++)
		{
		    for (kk=1;kk<=E->lmesh.nel;kk++)
			{

			    ibottom_node=E->ien[j][kk].node[1];
			    zbottom=E->sx[j][3][ibottom_node];

			    if (zbottom<E->composition.z_interface) E->trace.oldel[j][kk]=1.0;
			    if (zbottom>=E->composition.z_interface) E->trace.oldel[j][kk]=0.0;

			} /* end kk */
		} /* end j */
	}


    /* Else read from file */


    else if (E->trace.ic_method==2)
	{

	    /* first look for backing file */

	    sprintf(output_file,"%s.comp_el.%d.%d",E->control.old_P_file,E->parallel.me,E->monitor.solution_cycles_init);
	    if ( (fp=fopen(output_file,"r"))==NULL)
		{
                    fprintf(E->trace.fpt,"AKMerror(Initialize Old Composition)-FILE NOT EXIST: %s\n", output_file);
                    fflush(E->trace.fpt);
                    exit(10);
                }

            fgets(input_s,200,fp);

	    for(j=1;j<=E->sphere.caps_per_proc;j++)
		{
		    fgets(input_s,200,fp);
		    for (kk=1;kk<=E->lmesh.nel;kk++)
			{
			    fgets(input_s,200,fp);
			    sscanf(input_s,"%lf",&E->trace.oldel[j][kk]);
			}
		}

	    fclose(fp);

	} /* endif */



    return;
}



/*********** COMPUTE ELEMENTAL COMPOSITION RATIO METHOD ***/
/*                                                        */
/* This function computes the composition per element.    */
/* This function computes the composition per element.    */
/* Integer array ieltrac stores tracers per element.      */
/* Double array celtrac stores the sum of tracer composition */

void compute_elemental_composition_ratio_method(E)
     struct All_variables *E;
{

    int kk;
    int numtracers;
    int nelem;
    int j;
    int iempty=0;

    double comp;

    static int been_here=0;

    if (been_here==0)
	{
	    for (j=1;j<=E->sphere.caps_per_proc;j++)
		{

		    if ((E->trace.ieltrac[j]=(int *)malloc((E->lmesh.nel+1)*sizeof(int)))==NULL)
			{
			    fprintf(E->trace.fpt,"AKM(compute_elemental_composition)-no memory 5u83a\n");
			    fflush(E->trace.fpt);
			    exit(10);
			}
		    if ((E->trace.celtrac[j]=(double *)malloc((E->lmesh.nel+1)*sizeof(double)))==NULL)
			{
			    fprintf(E->trace.fpt,"AKM(compute_elemental_composition)-no memory 58hy8\n");
			    fflush(E->trace.fpt);
			    exit(10);
			}
		    if ((E->trace.comp_el[j]=(double *)malloc((E->lmesh.nel+1)*sizeof(double)))==NULL)
			{
			    fprintf(E->trace.fpt,"AKM(compute_elemental_composition)-no memory 8989y\n");
			    fflush(E->trace.fpt);
			    exit(10);
			}
		}

	    been_here++;

	}

    for (j=1;j<=E->sphere.caps_per_proc;j++)
	{

	    /* first zero arrays */

	    for (kk=1;kk<=E->lmesh.nel;kk++)
		{
		    E->trace.ieltrac[j][kk]=0;
		    E->trace.celtrac[j][kk]=0.0;
		}

	    numtracers=E->trace.itrac[j][0];

	    /* Fill ieltrac and celtrac */


	    for (kk=1;kk<=numtracers;kk++)
		{

		    nelem=E->trace.itrac[j][kk];
		    E->trace.ieltrac[j][nelem]++;

		    comp=E->trace.etrac[j][0][kk];

		    if (comp>1.0000001)
			{
			    fprintf(E->trace.fpt,"ERROR(compute elemental)-not ready for comp>1 yet (%f)(tr. %d) \n",comp,kk);
			    fflush(E->trace.fpt);
			    exit(10);
			}

		    E->trace.celtrac[j][nelem]=E->trace.celtrac[j][nelem]+comp;

		}

	    /* Check for empty entries and compute ratio.  */
	    /* If no tracers are in an element, use previous composition */

	    iempty=0;

	    for (kk=1;kk<=E->lmesh.nel;kk++)
		{

		    if (E->trace.ieltrac[j][kk]==0)
			{
			    iempty++;
			    E->trace.comp_el[j][kk]=E->trace.oldel[j][kk];
			}
		    else if (E->trace.ieltrac[j][kk]>0)
			{
			    E->trace.comp_el[j][kk]=E->trace.celtrac[j][kk]/(1.0*E->trace.ieltrac[j][kk]);
			}

		    if (E->trace.comp_el[j][kk]>(1.000001) || E->trace.comp_el[j][kk]<(-0.000001))
			{
			    fprintf(E->trace.fpt,"ERROR(compute elemental)-noway (3u5hd)\n");
			    fprintf(E->trace.fpt,"COMPEL: %f (%d)(%d)\n",E->trace.comp_el[j][kk],kk,E->trace.ieltrac[j][kk]);
			    fflush(E->trace.fpt);
			    exit(10);
			}
		}
	    if (iempty>0)
		{

		    /*
		      fprintf(E->trace.fpt,"%d empty elements filled with old values (%f percent)\n",iempty, (100.0*iempty/E->lmesh.nel));
		      fflush(E->trace.fpt);
		    */

		    if ((1.0*iempty/E->lmesh.nel)>0.80)
			{
			    fprintf(E->trace.fpt,"WARNING(compute_elemental...)-number of tracers is REALLY LOW\n");
			    fflush(E->trace.fpt);
			    if (E->trace.itracer_warnings==1) exit(10);
			}
		}

	    /* Fill oldel */


	    for (kk=1;kk<=E->lmesh.nel;kk++)
		{
		    E->trace.oldel[j][kk]=E->trace.comp_el[j][kk];
		}

	} /* end j */

    E->trace.istat_iempty=E->trace.istat_iempty+iempty;

    return;
}

/********** MAP COMPOSITION TO NODES ****************/
/*                                                  */


void map_composition_to_nodes(E)
     struct All_variables *E;
{

    int kk;
    int nelem, nodenum;
    int j;


    static int been_here=0;

    if (been_here==0)
	{

	    for (j=1;j<=E->sphere.caps_per_proc;j++)
		{

		    if ((E->trace.comp_node[j]=(double *)malloc((E->lmesh.nno+1)*sizeof(double)))==NULL)
			{
			    fprintf(E->trace.fpt,"AKM(map_compostion_to_nodes)-no memory 983rk\n");
			    fflush(E->trace.fpt);
			    exit(10);
			}
		}

	    been_here++;
	}

    for (j=1;j<=E->sphere.caps_per_proc;j++)
	{

	    /* first, initialize node array */

	    for (kk=1;kk<=E->lmesh.nno;kk++)
		{
		    E->trace.comp_node[j][kk]=0.0;
		}

	    /* Loop through all elements */

	    for (nelem=1;nelem<=E->lmesh.nel;nelem++)
		{

		    /* for each element, loop through element nodes */

		    /* weight composition */

		    for (nodenum=1;nodenum<=8;nodenum++)
			{

			    E->trace.comp_node[j][E->ien[j][nelem].node[nodenum]] +=
				E->trace.comp_el[j][nelem]*
				E->TWW[E->mesh.levmax][j][nelem].node[nodenum];

			}

		} /* end nelem */
	} /* end j */

    /* akm modified exchange node routine for doubles */

    (E->exchange_node_d)(E,E->trace.comp_node,E->mesh.levmax);

    /* Divide by nodal volume */

    for (j=1;j<=E->sphere.caps_per_proc;j++)
	{
	    for (kk=1;kk<=E->lmesh.nno;kk++)
		{
		    E->trace.comp_node[j][kk] *= E->MASS[E->mesh.levmax][j][kk];
		}

	    /* testing */
	    /*
	      for (kk=1;kk<=E->lmesh.nel;kk++)
	      {
	      fprintf(E->trace.fpt,"%d %f\n",kk,E->trace.comp_el[j][kk]);
	      }

	      for (kk=1;kk<=E->lmesh.nno;kk++)
	      {
	      fprintf(E->trace.fpt,"%d %f %f\n",kk,E->sx[j][3][kk],E->trace.comp_node[j][kk]);
	      }
	    */


	} /* end j */

    return;
}


/*********** GET BULK COMPOSITION *******************************/

void get_bulk_composition(E)
     struct All_variables *E;

{

    char output_file[200];
    char input_s[1000];

    double return_bulk_value_d();
    double volume;
    double rdum1;
    double rdum2;
    double rdum3;

    int ival=0;
    int idum1;
    int istep;


    FILE *fp;

    static int been_here=0;


    /* ival=0 returns integral not average */

    volume=return_bulk_value_d(E,E->composition.comp_node,ival);

    E->composition.bulk_composition=volume;

    /* Here we assume if restart = 1 or 0 tracers are reset          */
    /*                if restart = 2 tracers may or may not be reset  */
    /*                   (read initial composition from file)         */


    if (been_here==0)
	{
	    if (E->composition.ireset_initial_composition==1)
		{
		    E->composition.initial_bulk_composition=volume;
		}
	    else
		{

		    if (E->trace.ic_method!=2)
			{
			    fprintf(E->trace.fpt,"ERROR(bulk composition)-wrong reset,restart combo\n");
			    fflush(E->trace.fpt);
			    exit(10);
			}

		    sprintf(output_file,"%s.comp.%d.%d",E->control.old_P_file,
			    E->parallel.me,E->monitor.solution_cycles);

		    fp=fopen(output_file,"r");
		    fgets(input_s,200,fp);
		    sscanf(input_s,"%d %d %lf %lf %lf",
			   &istep,&idum1,&rdum1,&rdum2,&rdum3);

		    E->composition.initial_bulk_composition=rdum2;
		    fclose(fp);

		    if (istep!=E->monitor.solution_cycles)
			{
			    fprintf(E->trace.fpt,"ERROR(get_bulk_composition) %d %d\n",
				    istep,E->monitor.solution_cycles);
			    fflush(E->trace.fpt);
			    exit(10);
			}
		}
	}

    E->composition.error_fraction=((volume-E->composition.initial_bulk_composition)/
			     E->composition.initial_bulk_composition);

    parallel_process_sync(E);

    been_here++;
    return;
}



/******************* READ COMP ***********************************************/
/*                                                                           */
/* This function is similar to read_temp. It is used to read the composition */
/* from file for post-proceesing.                                            */

void read_comp(E)
     struct All_variables *E;
{
    int i,ii,m,mm,ll;
    char output_file[255],input_s[1000];

    double g;
    FILE *fp;



    ii = E->monitor.solution_cycles;
    sprintf(output_file,"%s.comp.%d.%d",E->control.old_P_file,E->parallel.me,ii);

    if ((fp=fopen(output_file,"r"))==NULL)
        {
	    fprintf(stderr,"ERROR(read_temp) - %s not found\n",output_file);
	    fflush(stderr);
	    exit(10);
        }

    fgets(input_s,1000,fp);
    sscanf(input_s,"%d %d %f",&ll,&mm,&E->monitor.elapsed_time);

    for(m=1;m<=E->sphere.caps_per_proc;m++)
        {
	    E->trace.comp_node[m]=(double *)malloc((E->lmesh.nno+1)*sizeof(double));

	    fgets(input_s,1000,fp);
	    sscanf(input_s,"%d %d",&ll,&mm);
	    for(i=1;i<=E->lmesh.nno;i++)
		{
		    if (fgets(input_s,1000,fp)==NULL)
			{
			    fprintf(stderr,"ERROR(read_comp) -data for node %d not found\n",i);
			    fflush(stderr);
			    exit(10);
			}
		    sscanf(input_s,"%lf",&g);
		    E->trace.comp_node[m][i] = g;

		}
        }

    fclose (fp);
    return;
}


back to top